Skip to main content

REST API Reference

Complete reference for the ZenOTC REST API. Use this documentation to integrate directly without the SDK.

Base URL

Production: https://api.zenotc.com
Staging: https://api-staging.zenotc.com

Authentication

All API requests require authentication via API key headers.

Required Headers

HeaderDescription
X-API-KeyYour API key
X-API-TimestampUnix timestamp in milliseconds
X-API-SignatureHMAC-SHA256 signature

Generating the Signature

import hmac
import hashlib
import time
import json

def generate_signature(api_secret: str, method: str, path: str, body: str = "") -> tuple[str, str]:
timestamp = str(int(time.time() * 1000))
message = f"{timestamp}{method.upper()}{path}{body}"
signature = hmac.new(
api_secret.encode(),
message.encode(),
hashlib.sha256
).hexdigest()
return timestamp, signature

Example Request

curl -X GET "https://api.zenotc.com/api/sdk/portfolio/balances" \
-H "X-API-Key: your_api_key" \
-H "X-API-Timestamp: 1705312200000" \
-H "X-API-Signature: abc123..."

Rate Limits

Endpoint CategoryRate Limit
Market Data30 requests/second
All Other Endpoints10 requests/second

Rate limit headers are included in responses:

  • X-RateLimit-Limit: Maximum requests per window
  • X-RateLimit-Remaining: Remaining requests
  • X-RateLimit-Reset: Window reset timestamp

API Key Scopes

ScopeDescription
READRead-only access to orders, portfolio, market data
TRADECreate, amend, cancel orders
MARKET_MAKINGSubmit and manage quotes
WITHDRAWInitiate withdrawals

Orders API

Create Order

Create a new order.

Endpoint: POST /api/sdk/orders Scope: TRADE

Request Body

FieldTypeRequiredDescription
sidestringYesbuy or sell
assetstringYesAsset symbol (e.g., BTC)
quantitynumberYesOrder quantity
pricenumberNoLimit price (required for limit orders)
orderTypestringNolimit (default) or market
timeInForcestringNoGTC (default), IOC, or FOK
clientOrderIdstringNoYour custom order ID (max 64 chars)
metadataobjectNoCustom metadata

Example Request

curl -X POST "https://api.zenotc.com/api/sdk/orders" \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key" \
-H "X-API-Timestamp: 1705312200000" \
-H "X-API-Signature: abc123..." \
-d '{
"side": "buy",
"asset": "BTC",
"quantity": 1.5,
"price": 50000.00,
"orderType": "limit",
"timeInForce": "GTC",
"clientOrderId": "my-order-123"
}'

Example Response

{
"orderId": "ord_abc123",
"clientOrderId": "my-order-123",
"side": "buy",
"asset": "BTC",
"quantity": 1.5,
"price": 50000.00,
"orderType": "limit",
"timeInForce": "GTC",
"status": "open",
"filledQuantity": 0,
"remainingQuantity": 1.5,
"averagePrice": null,
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z"
}

List Orders

Get a list of orders with optional filters.

Endpoint: GET /api/sdk/orders Scope: READ

Query Parameters

ParameterTypeDefaultDescription
statusesstring-Comma-separated: open, partially_filled, filled, cancelled
assetstring-Filter by asset
sidestring-Filter by side (buy/sell)
pagenumber1Page number
limitnumber50Results per page (max 100)

Example Request

curl -X GET "https://api.zenotc.com/api/sdk/orders?statuses=open,partially_filled&asset=BTC&limit=10" \
-H "X-API-Key: your_api_key" \
-H "X-API-Timestamp: 1705312200000" \
-H "X-API-Signature: abc123..."

Example Response

{
"orders": [
{
"orderId": "ord_abc123",
"side": "buy",
"asset": "BTC",
"quantity": 1.5,
"price": 50000.00,
"status": "open",
"filledQuantity": 0,
"createdAt": "2024-01-15T10:30:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 1,
"totalPages": 1
}
}

Get Order

Get details of a specific order.

Endpoint: GET /api/sdk/orders/:orderId Scope: READ

Example Request

curl -X GET "https://api.zenotc.com/api/sdk/orders/ord_abc123" \
-H "X-API-Key: your_api_key" \
-H "X-API-Timestamp: 1705312200000" \
-H "X-API-Signature: abc123..."

Get Order by Client ID

Retrieve an order using your custom client order ID.

Endpoint: GET /api/sdk/orders/by-client-id Scope: READ

Query Parameters

ParameterTypeRequiredDescription
clientOrderIdstringYesYour custom order ID

Example Request

curl -X GET "https://api.zenotc.com/api/sdk/orders/by-client-id?clientOrderId=my-order-123" \
-H "X-API-Key: your_api_key" \
-H "X-API-Timestamp: 1705312200000" \
-H "X-API-Signature: abc123..."

Amend Order

Modify an existing order's quantity or price.

Endpoint: PATCH /api/sdk/orders/:orderId Scope: TRADE

Request Body

FieldTypeRequiredDescription
quantitynumberNoNew quantity
pricenumberNoNew price

Example Request

curl -X PATCH "https://api.zenotc.com/api/sdk/orders/ord_abc123" \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key" \
-H "X-API-Timestamp: 1705312200000" \
-H "X-API-Signature: abc123..." \
-d '{
"quantity": 2.0,
"price": 51000.00
}'

Cancel Order

Cancel an open order.

Endpoint: DELETE /api/sdk/orders/:orderId Scope: TRADE

Example Request

curl -X DELETE "https://api.zenotc.com/api/sdk/orders/ord_abc123" \
-H "X-API-Key: your_api_key" \
-H "X-API-Timestamp: 1705312200000" \
-H "X-API-Signature: abc123..."

Example Response

{
"orderId": "ord_abc123",
"status": "cancelled",
"cancelledAt": "2024-01-15T10:35:00.000Z"
}

Get Order Fills

Get fills/trades for a specific order.

Endpoint: GET /api/sdk/orders/:orderId/fills Scope: READ

Example Response

{
"fills": [
{
"fillId": "fill_xyz789",
"orderId": "ord_abc123",
"price": 50000.00,
"quantity": 0.5,
"fee": 25.00,
"feeCurrency": "USD",
"executedAt": "2024-01-15T10:32:00.000Z"
}
]
}

Create Batch Orders

Create multiple orders in a single request.

Endpoint: POST /api/sdk/orders/batch Scope: TRADE

Request Body

FieldTypeRequiredDescription
ordersarrayYesArray of order objects (max 100)

Example Request

curl -X POST "https://api.zenotc.com/api/sdk/orders/batch" \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key" \
-H "X-API-Timestamp: 1705312200000" \
-H "X-API-Signature: abc123..." \
-d '{
"orders": [
{"side": "buy", "asset": "BTC", "quantity": 1.0, "price": 49000},
{"side": "buy", "asset": "BTC", "quantity": 1.0, "price": 48000},
{"side": "sell", "asset": "ETH", "quantity": 10.0, "price": 2500}
]
}'

Example Response

{
"results": [
{"success": true, "orderId": "ord_001", "clientOrderId": null},
{"success": true, "orderId": "ord_002", "clientOrderId": null},
{"success": true, "orderId": "ord_003", "clientOrderId": null}
],
"summary": {
"total": 3,
"successful": 3,
"failed": 0
}
}

Cancel All Orders

Cancel all open orders, optionally filtered by asset or side.

Endpoint: DELETE /api/sdk/orders/batch Scope: TRADE

Request Body

FieldTypeRequiredDescription
assetstringNoCancel only orders for this asset
sidestringNoCancel only buy or sell orders

Example Request

curl -X DELETE "https://api.zenotc.com/api/sdk/orders/batch" \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key" \
-H "X-API-Timestamp: 1705312200000" \
-H "X-API-Signature: abc123..." \
-d '{"asset": "BTC"}'

Quotes API (Market Making)

Submit Quote

Submit a two-sided quote (bid and ask).

Endpoint: POST /api/sdk/quotes Scope: MARKET_MAKING

Request Body

FieldTypeRequiredDescription
assetstringYesAsset symbol
bidPricenumberYesBid price
askPricenumberYesAsk price
bidSizenumberYesBid quantity
askSizenumberYesAsk quantity
validForSecondsnumberNoQuote validity (1-300, default 30)
clientQuoteIdstringNoYour custom quote ID
metadataobjectNoCustom metadata

Example Request

curl -X POST "https://api.zenotc.com/api/sdk/quotes" \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key" \
-H "X-API-Timestamp: 1705312200000" \
-H "X-API-Signature: abc123..." \
-d '{
"asset": "BTC",
"bidPrice": 49900.00,
"askPrice": 50100.00,
"bidSize": 5.0,
"askSize": 5.0,
"validForSeconds": 30
}'

Example Response

{
"quoteId": "quote_abc123",
"asset": "BTC",
"bidPrice": 49900.00,
"askPrice": 50100.00,
"bidSize": 5.0,
"askSize": 5.0,
"status": "active",
"expiresAt": "2024-01-15T10:30:30.000Z",
"createdAt": "2024-01-15T10:30:00.000Z"
}

List Quotes

Get a list of your quotes.

Endpoint: GET /api/sdk/quotes Scope: READ

Query Parameters

ParameterTypeDefaultDescription
statusstring-Filter: active, expired, filled, cancelled
assetstring-Filter by asset
limitnumber50Results per page
offsetnumber0Pagination offset

Get Quote

Get details of a specific quote.

Endpoint: GET /api/sdk/quotes/:quoteId Scope: READ


Update Quote

Update an active quote.

Endpoint: PATCH /api/sdk/quotes/:quoteId Scope: MARKET_MAKING

Request Body

FieldTypeRequiredDescription
bidPricenumberNoNew bid price
askPricenumberNoNew ask price
bidSizenumberNoNew bid size
askSizenumberNoNew ask size
validForSecondsnumberNoExtend validity

Cancel Quote

Cancel a specific quote.

Endpoint: DELETE /api/sdk/quotes/:quoteId Scope: MARKET_MAKING


Cancel All Quotes

Cancel all active quotes.

Endpoint: DELETE /api/sdk/quotes Scope: MARKET_MAKING

Request Body

FieldTypeRequiredDescription
assetstringNoCancel only quotes for this asset

Bulk Update Quotes

Update multiple quotes in a single request.

Endpoint: PATCH /api/sdk/quotes/batch/update Scope: MARKET_MAKING

Request Body

Array of quote updates:

[
{"quoteId": "quote_001", "bidPrice": 49950, "askPrice": 50050},
{"quoteId": "quote_002", "bidSize": 10, "askSize": 10}
]

Market Data API

Get Prices

Get current prices for assets.

Endpoint: GET /api/sdk/market-data/prices Scope: READ

Query Parameters

ParameterTypeDescription
assetsstringComma-separated list of assets (optional)

Example Request

curl -X GET "https://api.zenotc.com/api/sdk/market-data/prices?assets=BTC,ETH" \
-H "X-API-Key: your_api_key" \
-H "X-API-Timestamp: 1705312200000" \
-H "X-API-Signature: abc123..."

Example Response

{
"prices": [
{
"asset": "BTC",
"bid": 49950.00,
"ask": 50050.00,
"mid": 50000.00,
"last": 50010.00,
"change24h": 2.5,
"updatedAt": "2024-01-15T10:30:00.000Z"
},
{
"asset": "ETH",
"bid": 2495.00,
"ask": 2505.00,
"mid": 2500.00,
"last": 2502.00,
"change24h": 1.8,
"updatedAt": "2024-01-15T10:30:00.000Z"
}
]
}

Get Single Asset Price

Endpoint: GET /api/sdk/market-data/prices/:asset Scope: READ


Get Order Book

Get the order book for an asset.

Endpoint: GET /api/sdk/market-data/orderbook/:asset Scope: READ

Query Parameters

ParameterTypeDefaultDescription
depthnumber10Number of levels

Example Response

{
"asset": "BTC",
"bids": [
{"price": 49950.00, "quantity": 5.0},
{"price": 49900.00, "quantity": 10.0}
],
"asks": [
{"price": 50050.00, "quantity": 5.0},
{"price": 50100.00, "quantity": 8.0}
],
"timestamp": "2024-01-15T10:30:00.000Z"
}

Get Multiple Order Books

Endpoint: GET /api/sdk/market-data/orderbooks Scope: READ

Query Parameters

ParameterTypeRequiredDescription
assetsstringYesComma-separated list of assets
depthnumberNoNumber of levels (default 10)

Get Trading Pairs

Get available trading pairs.

Endpoint: GET /api/sdk/market-data/trading-pairs Scope: READ

Example Response

{
"pairs": [
{"base": "BTC", "quote": "USD", "minQuantity": 0.001, "maxQuantity": 100},
{"base": "ETH", "quote": "USD", "minQuantity": 0.01, "maxQuantity": 1000}
]
}

Get 24h Statistics

Endpoint: GET /api/sdk/market-data/stats/24h Scope: READ

Query Parameters

ParameterTypeDescription
assetstringFilter by asset (optional)

Example Response

{
"stats": [
{
"asset": "BTC",
"high": 51000.00,
"low": 48500.00,
"open": 49000.00,
"close": 50000.00,
"volume": 1250.5,
"volumeUsd": 62525000.00,
"trades": 847
}
]
}

Portfolio API

Get Balances

Get account balances.

Endpoint: GET /api/sdk/portfolio/balances Scope: READ

Query Parameters

ParameterTypeDescription
assetsstringComma-separated list of assets (optional)

Example Response

{
"balances": [
{
"asset": "BTC",
"total": 10.5,
"available": 8.0,
"locked": 2.5,
"usdValue": 525000.00
},
{
"asset": "USD",
"total": 100000.00,
"available": 75000.00,
"locked": 25000.00,
"usdValue": 100000.00
}
]
}

Get Single Asset Balance

Endpoint: GET /api/sdk/portfolio/balances/:asset Scope: READ


Get Positions

Get open positions.

Endpoint: GET /api/sdk/portfolio/positions Scope: READ

Query Parameters

ParameterTypeDescription
assetstringFilter by asset (optional)

Example Response

{
"positions": [
{
"asset": "BTC",
"quantity": 5.0,
"averageEntryPrice": 48000.00,
"currentPrice": 50000.00,
"unrealizedPnl": 10000.00,
"unrealizedPnlPercent": 4.17
}
]
}

Get Single Asset Position

Endpoint: GET /api/sdk/portfolio/positions/:asset Scope: READ


Get Portfolio Exposure

Endpoint: GET /api/sdk/portfolio/exposure Scope: READ

Example Response

{
"totalExposure": 625000.00,
"netExposure": 525000.00,
"longExposure": 525000.00,
"shortExposure": 0,
"byAsset": [
{"asset": "BTC", "exposure": 525000.00, "weight": 84.0},
{"asset": "USD", "exposure": 100000.00, "weight": 16.0}
]
}

Get Asset Exposure

Endpoint: GET /api/sdk/portfolio/exposure/:asset Scope: READ


Get Portfolio Summary

Endpoint: GET /api/sdk/portfolio/summary Scope: READ

Example Response

{
"totalValue": 625000.00,
"totalPnl": 15000.00,
"totalPnlPercent": 2.46,
"dayPnl": 5000.00,
"dayPnlPercent": 0.81,
"positions": 3,
"openOrders": 5
}

Get P&L Breakdown

Endpoint: GET /api/sdk/portfolio/pnl Scope: READ

Query Parameters

ParameterTypeDefaultDescription
periodstring24hPeriod: 1h, 24h, 7d, 30d

Get Transaction History

Endpoint: GET /api/sdk/portfolio/transactions Scope: READ

Query Parameters

ParameterTypeDescription
assetstringFilter by asset
typestringFilter by type: deposit, withdrawal, trade
pagenumberPage number
limitnumberResults per page

Get Trade History

Endpoint: GET /api/sdk/portfolio/trades Scope: READ

Query Parameters

ParameterTypeDescription
assetstringFilter by asset
sidestringFilter by side
startDatestringISO date string
endDatestringISO date string
pagenumberPage number
limitnumberResults per page

Get Available for Trading

Endpoint: GET /api/sdk/portfolio/available/:asset Scope: READ


Risk API

Get Risk Limits

Get your configured risk limits.

Endpoint: GET /api/sdk/risk/limits Scope: READ

Example Response

{
"limits": {
"maxOrderSize": {"BTC": 10, "ETH": 100},
"maxDailyVolume": 1000000.00,
"maxOpenOrders": 100,
"maxExposure": 5000000.00,
"maxExposurePerAsset": {"BTC": 1000000, "ETH": 500000}
}
}

Pre-Trade Risk Check

Validate an order against risk limits before submission.

Endpoint: POST /api/sdk/risk/pre-trade-check Scope: TRADE

Request Body

FieldTypeRequiredDescription
sidestringYesbuy or sell
assetstringYesAsset symbol
quantitynumberYesOrder quantity
pricenumberYesOrder price

Example Request

curl -X POST "https://api.zenotc.com/api/sdk/risk/pre-trade-check" \
-H "Content-Type: application/json" \
-H "X-API-Key: your_api_key" \
-H "X-API-Timestamp: 1705312200000" \
-H "X-API-Signature: abc123..." \
-d '{
"side": "buy",
"asset": "BTC",
"quantity": 5.0,
"price": 50000.00
}'

Example Response

{
"approved": true,
"checks": {
"orderSize": {"passed": true, "limit": 10, "value": 5},
"exposure": {"passed": true, "limit": 5000000, "value": 775000},
"dailyVolume": {"passed": true, "limit": 1000000, "value": 350000}
},
"warnings": []
}

Get Risk Exposure

Endpoint: GET /api/sdk/risk/exposure Scope: READ


Get Asset Risk Exposure

Endpoint: GET /api/sdk/risk/exposure/:asset Scope: READ


Get Limit Utilization

Endpoint: GET /api/sdk/risk/utilization Scope: READ

Example Response

{
"utilization": {
"exposure": {"used": 625000, "limit": 5000000, "percent": 12.5},
"dailyVolume": {"used": 350000, "limit": 1000000, "percent": 35.0},
"openOrders": {"used": 5, "limit": 100, "percent": 5.0}
}
}

Get Max Order Quantity

Calculate the maximum quantity you can order.

Endpoint: GET /api/sdk/risk/max-quantity Scope: READ

Query Parameters

ParameterTypeRequiredDescription
sidestringYesbuy or sell
assetstringYesAsset symbol
pricenumberYesOrder price

Example Response

{
"maxQuantity": 8.5,
"limitingFactor": "available_balance",
"details": {
"byBalance": 8.5,
"byExposure": 20.0,
"byOrderSizeLimit": 10.0
}
}

Get Risk Metrics

Endpoint: GET /api/sdk/risk/metrics Scope: READ


Simulate Order Impact

Simulate how an order would affect your portfolio.

Endpoint: POST /api/sdk/risk/simulate Scope: READ

Request Body

Same as Pre-Trade Check.

Example Response

{
"currentState": {
"exposure": 625000,
"btcPosition": 5.0
},
"afterOrder": {
"exposure": 875000,
"btcPosition": 10.0
},
"impact": {
"exposureChange": 250000,
"exposureChangePercent": 40.0
}
}

Error Responses

All errors follow a consistent format:

{
"statusCode": 400,
"message": "Invalid order parameters",
"error": "Bad Request",
"details": {
"field": "quantity",
"reason": "Must be greater than 0"
}
}

Common Error Codes

Status CodeDescription
400Bad Request - Invalid parameters
401Unauthorized - Invalid or missing API key
403Forbidden - Insufficient scope
404Not Found - Resource doesn't exist
429Too Many Requests - Rate limit exceeded
500Internal Server Error

Error Types

ErrorDescription
INVALID_API_KEYAPI key not found or revoked
INVALID_SIGNATURERequest signature verification failed
TIMESTAMP_EXPIREDRequest timestamp too old (>30s)
INSUFFICIENT_SCOPEAPI key lacks required scope
RATE_LIMIT_EXCEEDEDToo many requests
INSUFFICIENT_BALANCENot enough balance for operation
ORDER_NOT_FOUNDOrder ID doesn't exist
QUOTE_NOT_FOUNDQuote ID doesn't exist
RISK_LIMIT_EXCEEDEDOrder would breach risk limits