http://localhost:3000
Endpoint: POST /auth/register
Description: Creates a new user account with a default cash balance of $100,000.
Request Body:
{
"email": "string (valid email)",
"password": "string (min 6 characters)"
}Success Response (201):
{
"message": "User registered successfully",
"accessToken": "string",
"refreshToken": "string"
}Error Responses:
400- Invalid email or password format409- User already exists
Endpoint: POST /auth/login
Description: Authenticates user and returns JWT tokens.
Request Body:
{
"email": "string",
"password": "string"
}Success Response (200):
{
"message": "Login successful",
"accessToken": "string",
"refreshToken": "string"
}Error Responses:
400- Invalid request format401- Invalid credentials
Endpoint: POST /auth/refresh
Description: Generates new access and refresh tokens using a valid refresh token.
Request Body:
{
"refreshToken": "string"
}Success Response (200):
{
"message": "Token refreshed successfully",
"accessToken": "string",
"refreshToken": "string"
}Error Responses:
400- Refresh token required401- Invalid or expired refresh token
Note: All trading endpoints require authentication via Bearer token in the Authorization header.
Authorization Header:
Authorization: Bearer <accessToken>
Endpoint: POST /orders
Description: Creates a new order and enqueues it for processing.
Request Body:
{
"symbol": "string (1-10 chars)",
"side": "BUY | SELL",
"price": number (positive),
"quantity": number (positive integer)
}Validation Rules:
- BUY orders: User must have sufficient cash balance (price × quantity)
- SELL orders: User must have sufficient shares in position
- Price must be > 0
- Quantity must be > 0
Success Response (201):
{
"message": "Order created successfully",
"order": {
"id": "uuid",
"userId": "uuid",
"symbol": "AAPL",
"side": "BUY",
"price": "150.50",
"quantity": 10,
"remainingQuantity": 10,
"status": "NEW",
"createdAt": "2026-01-21T10:30:00.000Z"
}
}Error Responses:
400- Invalid input, insufficient funds/shares, or validation error401- Missing or invalid authentication token
Example Request:
curl -X POST http://localhost:3000/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGc..." \
-d '{
"symbol": "AAPL",
"side": "BUY",
"price": 150.50,
"quantity": 10
}'Endpoint: GET /orders/open
Description: Retrieves all open orders (NEW or PARTIALLY_FILLED) for the authenticated user.
Success Response (200):
{
"orders": [
{
"id": "uuid",
"userId": "uuid",
"symbol": "AAPL",
"side": "BUY",
"price": "150.50",
"quantity": 10,
"remainingQuantity": 10,
"status": "NEW",
"createdAt": "2026-01-21T10:30:00.000Z"
},
{
"id": "uuid",
"userId": "uuid",
"symbol": "GOOGL",
"side": "SELL",
"price": "2800.00",
"quantity": 5,
"remainingQuantity": 3,
"status": "PARTIALLY_FILLED",
"createdAt": "2026-01-21T09:15:00.000Z"
}
],
"count": 2
}Error Responses:
401- Missing or invalid authentication token
Example Request:
curl -X GET http://localhost:3000/orders/open \
-H "Authorization: Bearer eyJhbGc..."Endpoint: GET /portfolio
Description: Retrieves the authenticated user's cash balance and stock positions.
Success Response (200):
{
"cashBalance": "98495.00",
"positions": [
{
"symbol": "AAPL",
"quantity": 10
},
{
"symbol": "GOOGL",
"quantity": 5
},
{
"symbol": "TSLA",
"quantity": 15
}
]
}Notes:
- Cash balance is in USD
- Only positions with quantity > 0 are returned
- Empty positions array means no stock holdings
Error Responses:
401- Missing or invalid authentication token
Example Request:
curl -X GET http://localhost:3000/portfolio \
-H "Authorization: Bearer eyJhbGc..."Endpoint: GET /health
Description: Checks if the server is running.
Success Response (200):
{
"status": "ok",
"timestamp": "2026-01-21T10:30:00.000Z"
}Example Request:
curl http://localhost:3000/healthAll error responses follow this format:
{
"error": "Error message description",
"statusCode": 400
}Common HTTP Status Codes:
200- Success201- Created400- Bad Request (validation error)401- Unauthorized (missing/invalid token)404- Not Found409- Conflict (e.g., user already exists)500- Internal Server Error
curl -X POST http://localhost:3000/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "alice@trading.com",
"password": "securepass123"
}'Response:
{
"message": "User registered successfully",
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}curl -X GET http://localhost:3000/portfolio \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."Response:
{
"cashBalance": "100000.00",
"positions": []
}curl -X POST http://localhost:3000/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-d '{
"symbol": "AAPL",
"side": "BUY",
"price": 175.25,
"quantity": 50
}'Response:
{
"message": "Order created successfully",
"order": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"userId": "660e8400-e29b-41d4-a716-446655440001",
"symbol": "AAPL",
"side": "BUY",
"price": "175.25",
"quantity": 50,
"remainingQuantity": 50,
"status": "NEW",
"createdAt": "2026-01-21T10:30:00.000Z"
}
}curl -X GET http://localhost:3000/orders/open \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."Response:
{
"orders": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"userId": "660e8400-e29b-41d4-a716-446655440001",
"symbol": "AAPL",
"side": "BUY",
"price": "175.25",
"quantity": 50,
"remainingQuantity": 50,
"status": "NEW",
"createdAt": "2026-01-21T10:30:00.000Z"
}
],
"count": 1
}- User registers or logs in → receives
accessTokenandrefreshToken - User includes
accessTokenin Authorization header for protected routes - When
accessTokenexpires (after 15 minutes), userefreshTokento get new tokens - Repeat step 3 as needed (refresh tokens expire after 7 days)
- Access tokens expire in 15 minutes
- Refresh tokens expire in 7 days
- All monetary values are returned as strings to preserve decimal precision
- Orders are enqueued to Redis but not matched in Phase 1
- The matching engine will be implemented in a future phase