Authentication

JWT tokens, API keys, and MFA flows for secure API access

Authentication

The PRIME API supports two authentication methods: JWT Bearer Tokens for user sessions and API Keys for programmatic access.

Authentication Methods

MethodUse CaseHeader Format
Bearer TokenUser sessions (web/mobile)Authorization: Bearer <jwt>
API Key SignatureProgrammatic access (bots, integrations)Authorization: TDXV1-HMAC-SHA256 ...

Bearer Token Authentication

After login, use the JWT access token in the Authorization header.

Header Format

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

JWT Structure

The access token is a JWT signed with HMAC-SHA256 containing:

Standard Claims:

ClaimDescription
audAudience
expExpiration timestamp
iatIssued at timestamp
issIssuer
subSubject
jtiJWT ID

Custom Claims:

ClaimDescription
uidUser ID
utUser Type (FRONT_OFFICE, BACK_OFFICE, SYSTEM)
cidClient Account ID
unUsername
mfaMFA enabled flag
rRoles array
msModules array (e.g., "tdx", "issuers", "investors")

Token Lifecycle

TokenTypical ExpirationRenewal
Access Token1 hourUse refresh token
Session Token7 daysRe-authenticate

API Key Authentication

For programmatic access, use HMAC-SHA256 signed requests.

Header Format

Authorization: TDXV1-HMAC-SHA256 ApiKey=<api_key> Nonce=<uuid> Timestamp=<ms> Signature=<base64>

Components

ComponentFormatDescription
ApiKeyUUIDYour API key ID
NonceUUIDUnique per-request (prevents replay)
TimestampIntegerUTC timestamp in milliseconds
SignatureBase64HMAC-SHA256 signature

Signature Calculation

  1. Build the hash input (space-separated):

    TDXV1 <ApiKey> <Nonce> <Timestamp> <Method> <Host> <Path> <QueryString> <ContentType> <Body>
  2. Hash the input:

    hash = SHA256(input)
  3. Sign the hash:

    signature = Base64(HMAC-SHA256(apiSecret, hash))

Example (Python)

import hashlib
import hmac
import base64
import uuid
import time

api_key = "your-api-key-uuid"
api_secret = "your-api-secret"

nonce = str(uuid.uuid4())
timestamp = str(int(time.time() * 1000))
method = "GET"
host = "api.t-dx.com"
path = "/api/rest/v1/balances"
query = ""
content_type = ""
body = ""

# Build hash input
hash_input = f"TDXV1 {api_key} {nonce} {timestamp} {method} {host} {path} {query} {content_type} {body}"

# Calculate hash
hash_bytes = hashlib.sha256(hash_input.encode()).digest()
hash_b64 = base64.b64encode(hash_bytes).decode()

# Calculate signature
signature = base64.b64encode(
    hmac.new(api_secret.encode(), hash_b64.encode(), hashlib.sha256).digest()
).decode()

# Build header
auth_header = f"TDXV1-HMAC-SHA256 ApiKey={api_key} Nonce={nonce} Timestamp={timestamp} Signature={signature}"

Time Window

Requests must be within 150 seconds of the server time. Requests outside this window are rejected.


MFA (Multi-Factor Authentication)

When MFA is enabled for a user, login requires a TOTP code provided in the challenge field of the login request.

Login Flow with MFA

  1. Attempt Login Without TOTP - If MFA is enabled, returns error:

    POST /api/rest/v1/users/authentication/login
    {
      "username": "[email protected]",
      "password": "password123"
    }

    Response (401 Unauthorized):

    {
      "code": 16,
      "message": "MFA challenge required",
      "details": [{
        "@type": "type.googleapis.com/tgtraded.Error",
        "reason": "MFA_REQUIRED"
      }]
    }
  2. Login With TOTP Code - Include the challenge field:

    POST /api/rest/v1/users/authentication/login
    {
      "username": "[email protected]",
      "password": "password123",
      "challenge": "123456"
    }
  3. Receive Tokens - On success:

    {
      "result": {
        "accessToken": "eyJ...",
        "refreshToken": "session-uuid",
        "accessExpiresAt": "2024-01-15T11:30:00Z",
        "sessionExpiresAt": "2024-01-22T10:30:00Z"
      }
    }

Recovery Codes

Recovery codes are generated during MFA setup and can be used as alternatives to TOTP codes when the authenticator device is unavailable. Use a recovery code in place of the TOTP code in the challenge field.

Related Endpoints

EndpointDescription
POST /users/authentication/challenge/reset/initStart MFA reset flow
POST /users/authentication/challenge/resetComplete MFA reset
POST /users/authentication/challenge/validateValidate a TOTP code

Token Refresh

Before the access token expires, use the refresh token to obtain a new access token.

Request

POST /api/rest/v1/users/authentication/refresh
Content-Type: application/json

{
  "refreshToken": "session-uuid"
}

Response

{
  "result": {
    "accessToken": "eyJ...",
    "refreshToken": "session-uuid",
    "accessExpiresAt": "2024-01-15T11:30:00Z",
    "sessionExpiresAt": "2024-01-22T10:30:00Z"
  }
}

Authentication Errors

StatusReasonDescription
401UNAUTHENTICATEDMissing or invalid token
401MFA_REQUIREDMFA verification needed
403PERMISSION_DENIEDValid token but insufficient permissions
403ACCOUNT_IS_SUSPENDEDAccount suspended

Best Practices

  1. Store tokens securely - Never expose tokens in URLs or logs
  2. Refresh proactively - Refresh tokens before expiration
  3. Use API keys for automation - Don't embed user credentials in scripts
  4. Rotate API keys regularly - Create new keys and revoke old ones
  5. IP whitelist API keys - Restrict to known IP addresses
  6. Minimum permissions - Request only necessary permissions



  © 2025 Taurus SA. All rights reserved.