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