Skip to main content

Authentication

The Cadenza HTTP API uses OAuth2 Bearer token authentication. Tokens are obtained through the login endpoint and must be included in all authenticated requests.

Authentication Flow​

┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│ Client │ │ Cadenza │ │ Supabase │
│ │ │ API │ │ (IdP) │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
│ 1. POST /auth/login │
│────────────────────────────────────────
│ (email, password) │
│ │ │
│ │ 2. Validate │
│ │─────────────────▶│
│ │ │
│ │ 3. JWT Token │
│ │◀─────────────────│
│ │ │
│ 4. Access Token + Refresh Token │
│◀──────────────────│ │
│ │ │
│ 5. API Request (Bearer Token) │
│──────────────────▶│ │
│ │ │
│ 6. Response │ │
│◀──────────────────│ │

Login​

Authenticate with email and password to obtain tokens.

Request​

POST /api/v3/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "your-password"
}

Response​

{
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "v1.refresh-token-here",
"tokenType": "bearer",
"expiresIn": 3600,
"expiresAt": 1703056235,
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"createdAt": "2024-01-15T10:00:00Z"
}
},
"success": true,
"errno": 0,
"error": null
}

Example​

import requests

response = requests.post(
"https://cadenza-api-uat.algo724.com/api/v3/auth/login",
json={
"email": "user@example.com",
"password": "your-password"
}
)
data = response.json()["data"]

access_token = data["accessToken"]
refresh_token = data["refreshToken"]

Using the Access Token​

Include the access token in the Authorization header for all authenticated requests:

headers = {"Authorization": f"Bearer {access_token}"}

response = requests.get(
"https://cadenza-api-uat.algo724.com/api/v3/market/venue/list",
headers=headers
)
curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
https://cadenza-api-uat.algo724.com/api/v3/market/venue/list

Token Refresh​

Access tokens expire after a period (typically 1 hour). Use the refresh token to obtain a new access token without re-authenticating.

Request​

POST /api/v3/auth/token/refresh
Content-Type: application/json
{
"refreshToken": "v1.refresh-token-here"
}

Response​

{
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "v1.new-refresh-token-here",
"tokenType": "bearer",
"expiresIn": 3600,
"expiresAt": 1703059835,
"user": { ... }
},
"success": true,
"errno": 0,
"error": null
}

Example​

def refresh_access_token(refresh_token: str) -> dict:
response = requests.post(
"https://cadenza-api-uat.algo724.com/api/v3/auth/token/refresh",
json={"refreshToken": refresh_token}
)
response.raise_for_status()
return response.json()["data"]

# When token expires
new_session = refresh_access_token(refresh_token)
access_token = new_session["accessToken"]
refresh_token = new_session["refreshToken"] # Update refresh token too

Logout​

Invalidate the current session.

Request​

POST /api/v3/auth/logout
Authorization: Bearer {access_token}

Response​

{
"data": "ok",
"success": true,
"errno": 0,
"error": null
}

Get Current User​

Retrieve the authenticated user's information.

Request​

GET /api/v3/auth/user
Authorization: Bearer {access_token}

Response​

{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"emailConfirmedAt": "2024-01-15T10:00:00Z",
"phone": null,
"createdAt": "2024-01-15T10:00:00Z",
"updatedAt": "2024-01-15T10:00:00Z",
"userMetadata": {},
"appMetadata": {}
},
"success": true,
"errno": 0,
"error": null
}

Signup​

Create a new user account.

Request​

POST /api/v3/auth/signup
Content-Type: application/json
{
"email": "newuser@example.com",
"password": "secure-password"
}

Response​

Returns session with tokens (if auto-confirm is enabled) or user info (if email confirmation required).

Token Expiry Handling​

Implement automatic token refresh in your client:

import time

class CadenzaAuth:
def __init__(self, email: str, password: str):
self.base_url = "https://cadenza-api-uat.algo724.com"
self._login(email, password)

def _login(self, email: str, password: str):
response = requests.post(
f"{self.base_url}/api/v3/auth/login",
json={"email": email, "password": password}
)
response.raise_for_status()
self._update_tokens(response.json()["data"])

def _update_tokens(self, data: dict):
self.access_token = data["accessToken"]
self.refresh_token = data["refreshToken"]
self.expires_at = data["expiresAt"]

def _refresh_if_needed(self):
# Refresh 5 minutes before expiry
if time.time() > self.expires_at - 300:
response = requests.post(
f"{self.base_url}/api/v3/auth/token/refresh",
json={"refreshToken": self.refresh_token}
)
response.raise_for_status()
self._update_tokens(response.json()["data"])

def get_headers(self) -> dict:
self._refresh_if_needed()
return {"Authorization": f"Bearer {self.access_token}"}

Error Responses​

HTTP CodeErrorDescription
400Invalid credentialsEmail or password is incorrect
401UnauthorizedToken is invalid or expired
429Rate limitedToo many requests

Example Error​

{
"data": null,
"success": false,
"errno": -100001,
"error": "Invalid login credentials"
}

Security Best Practices​

  1. Never expose tokens - Store tokens securely, never in source code
  2. Use HTTPS - Always use HTTPS in production
  3. Implement refresh - Handle token expiry with automatic refresh
  4. Secure storage - Use secure storage for refresh tokens
  5. Logout on exit - Call logout when session ends

See Also​