Skip to content

Frontend API Integration Guide

Overview

This document provides the complete API reference for Frontend (Amplify) integration with TradAI platform. All endpoints are exposed through AWS API Gateway with JWT authentication via Cognito.


Quick Start

1. Get AWS Endpoints

AWS_PROFILE=tradai aws cloudformation describe-stacks \
  --stack-name tradai-edge-dev \
  --query 'Stacks[0].Outputs' \
  --region eu-central-1

2. Configure Amplify

// amplify.config.ts
import { Amplify } from 'aws-amplify';

Amplify.configure({
  Auth: {
    Cognito: {
      region: 'eu-central-1',
      userPoolId: 'eu-central-1_xxxxx',
      userPoolClientId: 'xxxxx',
      identityPoolId: 'eu-central-1:xxxxx',
    },
  },
  API: {
    REST: {
      endpoint: 'https://api.example.com', // or API Gateway endpoint
      region: 'eu-central-1',
    },
  },
});

3. Authenticate & Call API

import { signIn, fetchAuthSession } from 'aws-amplify/auth';
import { get } from 'aws-amplify/api';

// Login
const { isSignedIn, userId } = await signIn({ username, password });

// Get JWT Token
const session = await fetchAuthSession();
const token = session.tokens?.accessToken?.toString();

// Call API
const response = await get({
  apiName: 'tradai',
  path: '/api/v1/backtests',
  options: {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  },
}).response;

API Infrastructure

Network Architecture

  • API Gateway: HTTP API with VPC Link to ALB (Cognito JWT auth)
  • ALB: Proxies to ECS services via path-based routing
  • Service Discovery: Internal service communication via tradai-{env}.local
  • Authentication: Cognito User Pool JWT tokens

Deployment Stacks

Stack Components Outputs
persistent DynamoDB, S3, ECR, Cognito, Secrets Manager cognito_user_pool_id, cognito_user_pool_client_id, cognito_user_pool_endpoint
foundation VPC, Subnets, NAT, RDS, SQS, SNS vpc_id, private_subnet_ids, rds_endpoint
compute ALB, ECS, Lambda, Step Functions alb_dns_name, alb_https_listener_arn
edge API Gateway, WAF, CloudWatch api_gateway_endpoint, api_gateway_id, api_custom_domain

Service Endpoints (Internal)

Service Health Check Port Discovery Name
backend-api /api/v1/health 8000 backend-api.tradai-{env}.local
data-collection /api/v1/health 8002 data-collection.tradai-{env}.local
strategy-service /api/v1/health 8003 strategy-service.tradai-{env}.local
mlflow /mlflow/ 5000 mlflow.tradai-{env}.local

Base URLs

Development (Local)

HTTP:  http://localhost:8000
WS:    ws://localhost:8000

AWS (API Gateway)

HTTP:  https://{API_GATEWAY_ENDPOINT}  (auto-generated)
       https://{API_DOMAIN}             (custom domain if configured)
WS:    wss://{API_GATEWAY_ENDPOINT}
       wss://{API_DOMAIN}

Authentication Flow

1. Cognito OAuth2 Token Endpoint

Endpoint: https://{cognito-endpoint}/oauth2/token

Request (Client Credentials):

curl -X POST https://{cognito-endpoint}/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id={CLIENT_ID}" \
  -d "client_secret={CLIENT_SECRET}" \
  -d "grant_type=client_credentials" \
  -d "scope=tradai/api"

Response:

{
  "access_token": "eyJhbGc...",
  "token_type": "Bearer",
  "expires_in": 3600
}

2. Add to All Authenticated Requests

Authorization: Bearer {access_token}

JWT Token Details

  • Issuer: https://{cognito-endpoint}
  • Audience: {cognito_user_pool_client_id} or {cognito_m2m_client_id}
  • Expiry: 3600 seconds (1 hour)
  • Algorithm: RS256

Complete API Routes

All routes require JWT authentication except /api/v1/health.

Rate Limiting

  • Default: 100 req/s, burst 200
  • POST /api/v1/backtests: 10 req/s, burst 20 (throttled)

Route Table

HTTP Path Auth Rate Limit Purpose
Health & Status
GET /api/v1/health Health check
Backtests
POST /api/v1/backtests 10/s Submit backtest job
GET /api/v1/backtests 100/s List backtests (paginated)
GET /api/v1/backtests/{job_id} 100/s Get backtest status
POST /api/v1/backtests/{job_id}/cancel 100/s Cancel backtest
GET /api/v1/backtests/{job_id}/equity 100/s Equity curve data
GET /api/v1/backtests/{job_id}/report-data 100/s Full report data
Strategies
GET /api/v1/strategies 100/s List strategies
GET /api/v1/strategies/{id} 100/s Get strategy details
POST /api/v1/strategies 100/s Create strategy
POST /api/v1/strategies/{name}/stage 100/s Stage for validation
POST /api/v1/strategies/{name}/promote 100/s Promote to production
Catalog & Leaderboard
GET /api/v1/catalog/strategies 100/s Strategy leaderboard
GET /api/v1/catalog/strategies/{name} 100/s Catalog entry details
GET /api/v1/catalog/strategies/{name}/compare 100/s Compare versions
Data Management
GET /api/v1/data/symbols 100/s Available symbols
GET /api/v1/data/freshness 100/s Data freshness status
POST /api/v1/data/sync 100/s Sync market data
Model Management
GET /api/v1/models/{name}/versions 100/s List model versions
POST /api/v1/models/{name}/rollback 100/s Rollback version
MLflow Proxy
ANY /mlflow/{proxy+} 100/s MLflow API (wildcard)

Endpoint Details

Backtests

POST /api/v1/backtests

Submit a new backtest job (async).

Request:

{
  "strategy_config": {
    "name": "MyStrategy",
    "version": "1.0.0",
    "parameters": {
      "ma_period": 20,
      "threshold": 0.02
    }
  },
  "date_range": {
    "start": "2024-01-01T00:00:00Z",
    "end": "2024-12-31T23:59:59Z"
  },
  "exchange": "binance_futures",
  "timeframe": "1h",
  "capital": 10000,
  "leverage": 1.0
}

Response (201):

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "QUEUED",
  "created_at": "2024-01-01T00:00:00Z"
}

Errors: - 400: Validation error (invalid strategy, date range) - 422: Unprocessable entity (invalid capital/leverage) - 429: Rate limited (>10 req/s per IP)


GET /api/v1/backtests

List backtest jobs with pagination.

Query Parameters:

?limit=20&cursor=abc123&status_param=COMPLETED
- limit (int, 1-100, default=20): Results per page - cursor (string, optional): Pagination cursor - status_param (enum, optional): QUEUED | RUNNING | COMPLETED | FAILED | CANCELLED

Response:

{
  "jobs": [
    {
      "job_id": "550e8400-e29b-41d4-a716-446655440000",
      "status": "COMPLETED",
      "strategy_name": "MyStrategy",
      "strategy_version": "1.0.0",
      "created_at": "2024-01-01T00:00:00Z",
      "completed_at": "2024-01-02T12:30:45Z",
      "result": {
        "total_return": 0.1234,
        "sharpe_ratio": 1.45,
        "max_drawdown": -0.082,
        "trades_count": 42,
        "win_rate": 0.619,
        "profit_factor": 1.89
      }
    }
  ],
  "cursor": "next_cursor_token",
  "total": 156
}


GET /api/v1/backtests/{job_id}

Get specific backtest status and progress.

Path Parameters: - job_id (uuid): Backtest job ID

Response:

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "RUNNING",
  "strategy_name": "MyStrategy",
  "strategy_version": "1.0.0",
  "created_at": "2024-01-01T00:00:00Z",
  "progress": {
    "current": 75,
    "total": 100,
    "percentage": 75
  },
  "message": "Processing 2024-10 data..."
}

Statuses: - QUEUED: Waiting to start - RUNNING: Currently executing - COMPLETED: Finished successfully - FAILED: Execution error - CANCELLED: User cancelled


GET /api/v1/backtests/{job_id}/equity

Get equity curve data for visualization.

Response:

{
  "equity_curve": [
    {
      "timestamp": "2024-01-01T00:00:00Z",
      "portfolio_value": 10000,
      "drawdown_percent": 0
    },
    {
      "timestamp": "2024-01-01T01:00:00Z",
      "portfolio_value": 10150,
      "drawdown_percent": 0
    }
  ]
}


GET /api/v1/backtests/{job_id}/report-data

Get HTML-ready report data (for PDF/HTML generation).

Response:

{
  "summary": {
    "strategy": "MyStrategy",
    "period": "2024-01-01 to 2024-12-31"
  },
  "metrics": {
    "total_return": 0.1234,
    "sharpe_ratio": 1.45,
    "max_drawdown": -0.082,
    "trades": 42,
    "win_rate": 0.619
  },
  "trades": [
    {
      "entry_time": "2024-01-15T10:30:00Z",
      "exit_time": "2024-01-15T14:00:00Z",
      "symbol": "BTC/USDT:USDT",
      "side": "long",
      "entry_price": 42000,
      "exit_price": 42500,
      "pnl": 500
    }
  ],
  "charts": {
    "equity_curve_url": "...",
    "drawdown_url": "..."
  }
}


Strategies

GET /api/v1/strategies

List all strategies with filtering and sorting.

Query Parameters:

?stage=prod&exchange=binance_futures&timeframe=1h&search=trend&min_sharpe=1.0&sort_by=sharpe&sort_order=desc&limit=20&offset=0
- stage (enum): dev | staging | prod - exchange (string): binance_futures, etc. - timeframe (string): 1m, 5m, 1h, 4h, 1d - search (string): Keyword search - min_sharpe (float): Minimum Sharpe ratio filter - max_drawdown (float): Maximum drawdown % - sort_by (enum): name | sharpe | return | trades - sort_order (enum): asc | desc - limit (int, 1-100, default=20) - offset (int, pagination)

Response:

{
  "strategies": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "TrendFollower",
      "version": "1.0.0",
      "stage": "prod",
      "description": "SMA crossover trend following strategy",
      "metrics": {
        "sharpe_ratio": 1.67,
        "total_return": 0.2345,
        "max_drawdown": -0.095,
        "trades": 156,
        "win_rate": 0.641
      },
      "created_at": "2023-06-15T10:00:00Z",
      "updated_at": "2024-01-01T00:00:00Z"
    }
  ],
  "total": 42,
  "limit": 20,
  "offset": 0
}


GET /api/v1/catalog/strategies

Strategy leaderboard (composite scoring).

Same parameters and response structure as /api/v1/strategies, but with additional leaderboard ranking.


POST /api/v1/strategies/{name}/stage

Stage a strategy version for validation testing.

Path Parameters: - name (string): Strategy name

Request:

{
  "version": "1.0.0",
  "description": "Testing new parameters",
  "run_backtest": true
}

Response:

{
  "name": "TrendFollower",
  "version": "1.0.0",
  "stage": "staging",
  "status": "validation_in_progress",
  "created_at": "2024-01-01T00:00:00Z"
}


POST /api/v1/strategies/{name}/promote

Promote a strategy to production.

Path Parameters: - name (string): Strategy name

Request:

{
  "version": "1.0.0",
  "archive_previous": true
}

Response:

{
  "name": "TrendFollower",
  "version": "1.0.0",
  "stage": "prod",
  "promoted_at": "2024-01-01T00:00:00Z",
  "previous_version": "0.9.5"
}


Data Management

GET /api/v1/data/symbols?exchange=binance_futures

Get available trading symbols.

Query Parameters: - exchange (string, default="binance_futures"): Exchange identifier. Ignored when source="stored" — storage is shared across exchanges and returns all symbols in the library. The value is still echoed in the response. - source (string, default="exchange"): "exchange" lists every symbol the exchange advertises via CCXT; "stored" lists only symbols that already have OHLCV rows in ArcticDB.

Response:

{
  "symbols": [
    "BTC/USDT:USDT",
    "ETH/USDT:USDT",
    "SOL/USDT:USDT",
    "ADA/USDT:USDT"
  ],
  "exchange": "binance_futures",
  "count": 250,
  "last_updated": "2024-01-01T12:00:00Z"
}


GET /api/v1/data/freshness

Check data freshness for symbols.

Query Parameters:

?symbols[]=BTC/USDT:USDT&symbols[]=ETH/USDT:USDT&stale_threshold_hours=24
- symbols[] (array): Symbols to check - stale_threshold_hours (int, default=24): Freshness threshold

Response:

{
  "freshness": {
    "BTC/USDT:USDT": {
      "last_update": "2024-01-01T23:00:00Z",
      "hours_old": 5,
      "is_stale": false
    },
    "ETH/USDT:USDT": {
      "last_update": "2024-01-01T10:00:00Z",
      "hours_old": 18,
      "is_stale": false
    }
  },
  "threshold_hours": 24,
  "checked_at": "2024-01-02T04:00:00Z"
}


POST /api/v1/data/sync

Sync market data from exchange.

Request:

{
  "symbols": ["BTC/USDT:USDT", "ETH/USDT:USDT"],
  "exchange": "binance_futures",
  "force_refresh": false
}

Response:

{
  "status": "completed",
  "symbols_synced": 2,
  "new_rows": 480,
  "sync_duration_ms": 2340,
  "completed_at": "2024-01-02T04:15:30Z"
}


Model Management

GET /api/v1/models/{model_name}/versions

List all versions of a model.

Query Parameters: - include_archived (bool, default=true): Include archived versions

Response:

{
  "model_name": "price-predictor",
  "versions": [
    {
      "version": "1.2.0",
      "stage": "prod",
      "created_at": "2024-01-01T00:00:00Z",
      "metrics": {
        "accuracy": 0.924,
        "auc": 0.881,
        "f1_score": 0.867
      },
      "archived": false
    },
    {
      "version": "1.1.0",
      "stage": "archived",
      "created_at": "2023-12-15T00:00:00Z",
      "metrics": {
        "accuracy": 0.912,
        "auc": 0.868,
        "f1_score": 0.854
      },
      "archived": true
    }
  ]
}


POST /api/v1/models/{model_name}/rollback

Rollback to a previous model version.

Path Parameters: - model_name (string): Model name

Request:

{
  "target_version": "1.1.0",
  "dry_run": false
}

Response:

{
  "model_name": "price-predictor",
  "previous_version": "1.2.0",
  "rolled_back_to": "1.1.0",
  "status": "completed",
  "timestamp": "2024-01-02T04:30:00Z"
}


WebSocket Real-Time Updates

WS /ws/backtests/{job_id}

Stream backtest progress in real-time.

Authentication: 1. Get single-use ticket:

POST /ws/ticket
Response: { "ticket": "jwt_token" }

  1. Connect with ticket:
    ws://api.example.com/ws/backtests/{job_id}?ticket={jwt_token}
    

Server Messages (JSON):

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "RUNNING",
  "progress": {
    "current": 50,
    "total": 100,
    "percentage": 50
  },
  "message": "Processing 2024-06 data..."
}

When completed:

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "COMPLETED",
  "result": {
    "total_return": 0.1234,
    "sharpe_ratio": 1.45,
    "max_drawdown": -0.082
  }
}

Close Codes: - 1000: Normal closure - 1008: Policy violation (auth failed, connection limit exceeded) - 1011: Server error

Connection Limits: Configurable per job (default: 10 concurrent connections)


Error Handling

HTTP Status Codes

Code Meaning Example
200 Success GET request completed
201 Created POST /backtests accepted
400 Bad Request Invalid parameters
401 Unauthorized Missing/invalid JWT
403 Forbidden Insufficient permissions
404 Not Found Job/strategy doesn't exist
422 Unprocessable Invalid data (semantic error)
429 Too Many Requests Rate limit exceeded
500 Server Error Internal error
503 Service Unavailable Service down

Error Response Format

{
  "detail": "Descriptive error message",
  "code": "ERROR_CODE",
  "timestamp": "2024-01-01T00:00:00Z"
}

CORS Configuration

Allowed Origins (configurable): - Dev: * (all) - Staging/Prod: Set via Pulumi config

Allowed Methods: GET, POST, PUT, DELETE, OPTIONS Allowed Headers: Authorization, Content-Type, X-Amz-Date Max Age: 86400 (24 hours)


Implementation Checklist

  • Retrieve AWS outputs (Cognito, API Gateway endpoints)
  • Configure Amplify with Cognito credentials
  • Implement JWT token acquisition
  • Add Authorization header to all authenticated requests
  • Test GET /api/v1/health (public endpoint)
  • Test authentication flow with token refresh
  • Implement pagination for list endpoints
  • Handle WebSocket connection with single-use tickets
  • Implement rate limiting retry logic (429 responses)
  • Test CORS preflight requests
  • Verify error handling for all status codes
  • Implement exponential backoff for retries
  • Test with mock data before live integration

Reference Files

  • Config: infra/shared/tradai_infra_shared/config.py
  • API Gateway: infra/edge/modules/api_gateway.py
  • Backend API: services/backend/src/tradai/backend/api/
  • Data Collection: services/data-collection/src/tradai/data_collection/api/
  • Strategy Service: services/strategy-service/src/tradai/strategy_service/api/

Last Updated: 2024-01-02 Document Version: 1.0