Genesis Trading API: Introduction
Version: 1.3.9
Last Updated: July, 14, 2022
The REST API documentation for Genesis Trading explains the input, output, and endpoint URL for each API to help you use them effectively.
For more information and any queries, Genesis API team can be reached at Send an email to Genesis API Team for questions related to API onboarding, connectivity issues, API availability, trading support, and more.
If you wish to receive notifications regarding scheduled maintenance windows and new features, please provide an appropriate email distribution for those.
Revision History
Date | Version | Summary |
---|---|---|
03/19/2020 | 1.0.0 | Initial release |
04/15/2020 | 1.0.1 | Added rate limits and improved documentation |
05/29/2020 | 1.0.2 | Changed /stream to asynchronous design |
08/31/2020 | 1.1.0 | Clarified language |
1.1.1 | Clarified language | |
1.1.2 | Added “Account” to /orderStatus and /stream | |
01/07/2021 | 1.2.0 | New /balanceStatus endpoint, updated maintenance window, and ergonomic field naming changes |
01/13/2021 | 1.2.1 | Updated /stream response field and accepted fields for ‘TimeInForce’ arguments |
04/08/2021 | 1.3.0 | Added market order submissions |
04/28/2021 | 1.3.1 | Clarified language on partially filled orders |
05/14/2021 | 1.3.2 | Added /metadata endpoint |
07/13/2021 | 1.3.3 | Added /settlementStatus and /tradeHistory endpoints |
07/22/2021 | 1.3.4 | Updated /securityDefinitionRequest with price / quantity precision. Added additional error messaging. |
08/13/2021 | 1.3.5 | Added /quote endpoint and order reject / cancel messaging. |
09/23/2021 | 1.3.6 | Added pagination for /settlementStatus and added support for multi-level streaming IOC orders. |
10/14/2021 | 1.3.7 | Added support for IOC market orders |
02/03/2022 | 1.3.8 | Added /sseStream endpoint. Removed information on the nonce order validation. |
05/19/2022 | 1.3.9 | Added workflow to initiate a request for new coins. |
API Support & Availability
Support Escalation
The Genesis API Support team can be directly reached at api@genesistrading.com for questions related to API onboarding, connectivity issues, API availability, trading support, and more.
For general support questions, please contact support@genesistrading.com
New features and maintenance notifications
If you wish to receive notifications regarding scheduled maintenance windows and new features, please send your appropriate email distribution to api@genesistrading.com
Availability
The Genesis Trading REST API is intended to facilitate market data and order entry.
Env | Description |
---|---|
Production | 24/7/365 with a daily maintenance window where the system will be entirely offline. The maintenance window runs between 16:30 and 16:55 ET. |
UAT | 24/7/365 with a variable maintenance window. Changes will be communicated through the Support team. |
Connectivity
Endpoints
IP whitelisting is required for all endpoints.
Environment | Endpoint |
---|---|
Production | https://api.genesistrading.com |
UAT | https://trading.uat.genesistrading.com |
Protocols and Verbs
All REST requests are communicated over HTTPS. REST requests should be made with the POST verb. Server-sent events (SSE) streaming URL requests should be made with the GET verb.
Streaming
The streaming HTTPS request will "time-out" after 300 seconds if no other REST request is made within that time interval. We recommend sending a keep-alive ping call every 60 seconds to keep the stream connected. WebSocket connections are not supported.
Rate limiting
By default, all clients are configured with the following global rate limits across all API methods. Rate limits are implemented using a “token bucket” of size equal to the max burst rate and refill rate equal to the request rate. Rate limits are enforced per client IP address, not per API key.
Description | Rate limit |
---|---|
Max burst per IP | 1000 requests/second |
Request rate per IP | 100 requests/second |
Error handling and Best Practices
Error codes
Error codes | Value | Description |
---|---|---|
OK | 0 | No Error |
TooManyRequests | 1 | Requests for client IP have exceeded rate limit |
Unauthorized | 2 | Invalid client API key or client account |
Unsupported method | 3 | Invalid REST verb or URL |
Invalid signature | 4 | Signature string is invalid |
Missing argument | 5 | A required argument was missing for the specific endpoint |
Invalid argument | 6 | |
Invalid nonce | 7 | |
New order error | 1001 | A specific error occurred when creating a new order |
Unknown Error | 9999 | Generic error code |
Retry Logic - Detection & Reconnection
During scheduled maintenance windows or any unexpected outages, all requests will return an HTTP 5XX server error and the SSE connection will be closed. Upon detection, we recommend implementing retry logic to reopen the stream every 60 seconds until a stream connection is successfully secured. Please note that following scheduled maintenance windows or any unexpected outage, you will need to send a subscription request via the /marketDataRequest endpoint to receive market data or submit orders.
Nonces - Ordering & Tolerance
We require strict ordering and uniqueness of nonce values received over the API gateway to ensure sequenced processing of these messages. If your implementation involves parallel processes making API requests, all calls should be directed through an outbound service that tags the requests with the appropriate nonce and signature.
Authentication
Message Format Examples:
# ?APIKEY=apikey&PAYLOAD=payload&NONCE=nonce&SIGNATURE=signature
import hmac
import time
import requests
def generate_query_params(args):
payload = json.dumps(args) #'null' if none
nonce = str(int(time.time() * 1e9)) # nanosecond
signature = hmac.new(api_secret.encode(), (api_key + payload + nonce).encode(),
hashlib.sha384).hexdigest()
query_params = {
"APIKEY": api_key,
"PAYLOAD": payload,
"NONCE": nonce,
"SIGNATURE": signature,
}
return query_params
The following fields should be URL-encoded for all requests. Arguments for a specific method are passed as a standard JSON object in the PAYLOAD field.
Field Name | Datatype | Description |
---|---|---|
APIKEY | string | Client API key |
PAYLOAD | string | URL encoded JSON object specifying request arguments. Must be 'null' if none. |
NONCE | number | Unix timestamp with nanosecond precision (the number of nanoseconds elapsed since January 1, 1970 UTC). Requests older than 10 seconds will be considered stale and will not be processed as a safety mechanism. |
SIGNATURE | string | Hex digest of SHA384 hash of the concatenation of APIKEY + PAYLOAD + NONCE, using the client API secret |
List of API Endpoints
URL | Description |
---|---|
POST /ping | No operation. Used to keep stream alive or test connectivity |
POST /securityDefinitionRequest | Retrieve an array of tradable symbols with properties |
POST /metadata | Retrieve configuration information |
POST /marketDataRequest | Subscribe to market data |
GET /sseStream | Opens multiple market data streams with limit of 10 |
POST /quote | Retrieve current L2 update |
POST /newOrderSingle | Send a new order |
POST /orderStatus | Retrieve execution reports for a given order |
POST /tradeHistory | Retrieve trade history for the specified date range |
POST /balanceStatus | Retrieve the outstanding quantity of unsettled trades by symbol |
POST /settlementStatus | Retrieve trade batch settlement amounts |
Recommended API Workflows
API Endpoints
Ping
import requests
url = "https://<trading-api-url>/ping?APIKEY=API_KEY_VALUE&PAYLOAD=null&NONCE=1634241864011000000&SIGNATURE=91f0bb5c89b01235ded238b82f9613cdeeb76bf8d1f15470890927a684b2bea0e4fa08b4bc628a67434b4c8cb37e355a"
payload = ""
response = requests.request("POST", url, headers=headers, data=payload)
The above command returns JSON structured like this:
{
"ErrorStatus": 0,
"SendingTime": 1633963791265166639,
"Result": "PONG",
"Text": "Success"
}
A no-operation request to reset the stream timeout interval or test connectivity.
HTTP Request
POST https:<trading-api-url>/ping?APIKEY=KEY&PAYLOAD=PL&NONCE=NC&SIGNATURE=SIGNATURE
Arguments
None
Response
Field | Datatype | Description |
---|---|---|
ErrorStatus | number | 0 if OK, error code otherwise. |
SendingTime | number | Unix timestamp with nanosecond precision. |
Result | string | 'PONG' |
Text | string | ‘Success’ or reason for error |
Security Definition Request
import requests
url = "https://<trading-api-url>/securityDefinitionRequest?APIKEY=APIKEY_VALUE&PAYLOAD=null&NONCE=1634241864011000000&SIGNATURE=91f0bb5c89b01235ded238b82f9613cdeeb76bf8d1f15470890927a684b2bea0e4fa08b4bc628a67434b4c8cb37e355a"
payload = ""
response = requests.request("POST", url, headers=headers, data=payload)
The above command returns JSON structured like this:
{
"ErrorStatus": 0,
"SendingTime": 1632932207589991721,
"Result": [
{
"Symbol": "ETH-USD",
"MinQty": 0.00000001,
"QtyPrecision": 8,
"PricePrecision": 2
},
{
"Symbol": "BTC-USD",
"MinQty": 0.00000001,
"QtyPrecision": 8,
"PricePrecision": 2
}
],
"Text": "Success"
}
Retrieves the symbols allowed for trading and their properties. Precisions are defined as the maximum number of decimal places this field supports.
HTTP Request
POST https:<trading-api-url>/securityDefinitionRequest?APIKEY=KEY&PAYLOAD=PL&NONCE=NC&SIGNATURE=SIGNATURE
Arguments
None
Response
Field | Datatype | Description |
---|---|---|
ErrorStatus | number | 0 if OK, error code otherwise. |
SendingTime | number | Unix timestamp with nanosecond precision. |
Result | array(Object) | [{ 'Symbol': string, 'MinQty': number, ‘QtyPrecision’: number, ‘PricePrecision’: number},...] |
Text | string | ‘Success’ or reason for error |
Market data Request
import requests
payload = {'Action': 'SUBSCRIBE', 'Symbols': ['BTC-USD', 'ETH-USD', 'LTC-USD']}
url = "https://<trading-api-url>/marketDataRequest?APIKEY=11213&PAYLOAD="+ payload +"&NONCE=1634241864011000000&SIGNATURE=91f0bb5c89b01235ded238b82f9613cdeeb76bf8d1f15470890927a684b2bea0e4fa08b4bc628a67434b4c8cb37e355a"
response = requests.request("POST", url, headers=headers, data=payload)
The above command returns JSON structured like this:
{
"ErrorStatus": 0,
"SendingTime": 1635224837518606767,
"Result": null,
"Text": "Success: requested symbols: BTC-USD,ETC-USD,LTC-USD, subscribed/unsubscribed symbols: BTC-USD,ETC-USD,LTC-USD"
}
Add symbols to the streaming URL. L2 updates returned on /stream. Subscriptions remain active until unsubscribe or /logout.
HTTP Request
POST https:<trading-api-url>/marketDataRequest?APIKEY=KEY&PAYLOAD=PL&NONCE=NC&SIGNATURE=SIGNATURE
Arguments
Argument | Datatype | Description |
---|---|---|
Action | string | Accepted: 'SUBSCRIBE' or 'UNSUBSCRIBE' |
Symbols | array (string) | An array of string symbols to subscribe/unsubscribe |
Response
Field | Datatype | Description |
---|---|---|
ErrorStatus | number | 0 if OK, error code otherwise. |
SendingTime | number | Unix timestamp with nanosecond precision. |
Result | null | null |
Text | string | ‘Success: requested symbols: {client requested symbols}, subscribed/unsubscribed symbols: {successfully subscribed/unsubscribed symbols}’ or reason for error |
Quote
import requests
payload = {"Symbol":"BTC-USD"}
url = "https://<trading-api-url>/quote?APIKEY=11213&PAYLOAD="+ payload +"&NONCE=1634241864011000000&SIGNATURE=91f0bb5c89b01235ded238b82f9613cdeeb76bf8d1f15470890927a684b2bea0e4fa08b4bc628a67434b4c8cb37e355a"
response = requests.request("POST", url, headers=headers, data=payload)
The above command returns JSON structured like this:
{
"ErrorStatus": 0,
"SendingTime": 1635306311921354653,
"Result": {
"QuoteTime": 1635306310561884347,
"ValidUntil": 1635306315561182283,
"Symbol": "BTC-USD",
"Changes": [
{
"Entry": [
"BUY",
60302.28,
0
]
},
{
"Entry": [
"SELL",
61104.79,
0
]
},
{
"Entry": [
"BUY",
60277.82,
1000
]
},
{
"Entry": [
"SELL",
61141.5,
1000
]
}
],
"Venue": "GENESIS"
},
"Text": "Success"
}
Retrieve the latest L2 update for a given symbol. Prior to sending a /quote request, please submit a successful subscription request for the given symbol via the /marketDataRequest endpoint.
HTTP Request
POST https:<trading-api-url>/quote?APIKEY=KEY&PAYLOAD=PL&NONCE=NC&SIGNATURE=SIGNATURE
Arguments
Argument | Datatype | Description |
---|---|---|
Symbol | string | Symbol to pull quote for (e.g. ‘BTC-USD’) |
Response
Field | Datatype | Description |
---|---|---|
ErrorStatus | number | 0 if OK, error code otherwise. |
SendingTime | number | Unix timestamp with nanosecond precision. |
Result | object | L2 Update with multi-level quote { Venue: 'GENESIS', QuoteTime: number (Unix timestamp w/ ns precision), ValidUntil: number (Unix timestamp w/ ns precision), Symbol: string, Changes: [{‘Entry’: [string number number]}, {‘Entry’: [string number number]},...] e.g. [{‘Entry’: ['BUY' price qty]}, {‘Entry’: ['BUY' price qty]} {‘Entry’: ['SELL' price qty]} {‘Entry’: ['SELL' price qty]},...] } |
Text | string | Success |
NewOrderSingle
import requests
payload = {"Symbol":"BTC-USD","ClOrdID":"299808394218321","OrdType":"MARKET","TimeInForce":"FILL_OR_KILL","Side":"BUY","OrderQty":0.01, "Price": 0}
url = "https://<trading-api-url>/newOrderSingle?APIKEY=11213&PAYLOAD="+ payload +"&NONCE=1634241864011000000&SIGNATURE=91f0bb5c89b01235ded238b82f9613cdeeb76bf8d1f15470890927a684b2bea0e4fa08b4bc628a67434b4c8cb37e355a"
response = requests.request("POST", url, headers=headers, data=payload)
The above command returns JSON structured like this:
{
"ErrorStatus": 0,
"SendingTime": 1635225609292793427,
"Result": null,
"Text": "Success"
}
Submit a new order. Execution report returned on /stream.
HTTP Request
POST https:<trading-api-url>/newOrderSingle?APIKEY=KEY&PAYLOAD=PL&NONCE=NC&SIGNATURE=SIGNATURE
Arguments
Argument | Datatype | Description |
---|---|---|
Symbol | string | Symbol identifier |
ClOrdID | string (string) | Client-specified unique order identifier. Must be <= 32 characters in length. |
OrdType* | string | Accepted: 'LIMIT' or 'MARKET' |
TimeInForce** | string | Accepted: 'FILL_OR_KILL' or 'IMMEDIATE_OR_CANCEL' |
Side | string | Accepted: 'BUY' or 'SELL' |
Price | number | Required for OrdType ‘LIMIT’ |
OrderQty | number | Order size in units of given symbol. See /securityDefinitionRequest for qty precision by symbol. |
* For market orders, we currently support FOK. We will be releasing support for market IOC orders in the next update.
** For clients enabled for 2+ order book levels, only immediate-or-cancel orders will be accepted.
Response
Field | Datatype | Description |
---|---|---|
ErrorStatus | number | 0 if OK, error code otherwise. |
SendingTime | number | Unix timestamp with nanosecond precision. |
Result | null | null |
Text | string | ‘Success’ or reason for error |
Order Status
import requests
payload = {"ClOrdId":"576048115236807"}
url = "https://<trading-api-url>/orderStatus?APIKEY=11213&PAYLOAD="+ payload +"&NONCE=1634241864011000000&SIGNATURE=91f0bb5c89b01235ded238b82f9613cdeeb76bf8d1f15470890927a684b2bea0e4fa08b4bc628a67434b4c8cb37e355a"
response = requests.request("POST", url, headers=headers, data=payload)
The above command returns JSON structured like this:
{
"ErrorStatus": 0,
"SendingTime": 1635307485199219381,
"Result": [
{
"OrdID": "8374283749237498273",
"Account": "key",
"ClOrdID": "128371827481827",
"TransactTime": 1635307481965122901,
"OrdType": "MARKET",
"OrdStatus": "FILLED",
"TimeInForce": "FILL_OR_KILL",
"Symbol": "BTC-USD",
"Side": "BUY",
"OrderQty": 0.01,
"Price": 0,
"LastPx": 61006.46,
"LastQty": 0.01,
"LeavesQty": 0,
"CumQty": 0.01,
"AvgPx": 61006.46,
"Text": "Filled"
}
],
"Text": "Success"
}
Obtain the chronologically ordered execution report history for one order.
Field Descriptions
The price and quantity fields of the execution report for a given order is in accordance with FIX specifications.
HTTP Request
POST https:<trading-api-url>/orderStatus?APIKEY=KEY&PAYLOAD=PL&NONCE=NC&SIGNATURE=SIGNATURE
Arguments
Argument | Datatype | Description |
---|---|---|
ClOrdID | string | The order’s client-set ClOrdID |
Response
Field | Datatype | Description |
---|---|---|
ErrorStatus | number | 0 if OK, error code otherwise. |
SendingTime | number | Unix timestamp with nanosecond precision. |
Result | array(object) | [{ OrdID: string, Account: string, ClOrdID: string, TransactTime: number (Unix timestamp w/ ns precision), OrdType: string ('LIMIT' or 'MARKET'), OrdStatus: string ('FILLED', 'PARTIALLY_FILLED', 'CANCELLED', or 'ORDER_REJECTED'), TimeInForce: string ('FILL_OR_KILL' or 'IMMEDIATE_OR_CANCEL'), Symbol: string (e.g. 'BTC-USD'), Side: string ('BUY' or 'SELL'), OrderQty: number, Price: number, LastPx: number, LastQty: number, LeavesQty: number, CumQty: number, AvgPx: number, Text: string ('Filled' or cancel reason) },...] |
Text | string | ‘Success’ or reason for error |
Trade history
import requests
payload = {"StartTime":1635223770045000000, "EndTime":1635310170046000000, "OrderDesc": true}
url = "https://<trading-api-url>/tradeHistory?APIKEY=11213&PAYLOAD="+ payload +"&NONCE=1634241864011000000&SIGNATURE=91f0bb5c89b01235ded238b82f9613cdeeb76bf8d1f15470890927a684b2bea0e4fa08b4bc628a67434b4c8cb37e355a"
response = requests.request("POST", url, headers=headers, data=payload)
The above command returns JSON structured like this:
{
"ErrorStatus": 0,
"SendingTime": 1635310170267334350,
"Result": [
{
"OrdID": "123123123123123",
"Account": "key",
"ClOrdID": "207090116513944",
"TransactTime": 1635307481965122901,
"OrdType": "MARKET",
"OrdStatus": "FILLED",
"TimeInForce": "FILL_OR_KILL",
"Symbol": "BTC-USD",
"Side": "BUY",
"OrderQty": 0.01,
"Price": 0,
"LastPx": 61006.46,
"LastQty": 0.01,
"LeavesQty": 0,
"CumQty": 0.01,
"AvgPx": 61006.46,
"Text": "Filled"
}
],
"Text": "Success"
}
Obtain the chronologically ordered execution report history for orders that were filled or partially filled.
To paginate results, the ‘StartTime’ value of the subsequent /tradeHistory request should be populated with the ‘EndTime’ value of the previous response.
HTTP Request
POST https:<trading-api-url>/tradeHistory?APIKEY=KEY&PAYLOAD=PL&NONCE=NC&SIGNATURE=SIGNATURE
Arguments
Argument | Datatype | Description |
---|---|---|
StartTime | number | Unix timestamp with nanosecond precision. Exclusive of given range. Else 0 for beginning of time. |
EndTime | number | Unix timestamp with nanosecond precision. Inclusive of given range. |
Limit | number | Optional - Number of orders (Default set to 20, otherwise 1 <= Limit <= 100) |
Side | string | Optional - Side to filter for (‘BUY’ or ‘SELL’) |
Symbol | string | Optional - Symbol to filter for (e.g. ‘BTC-USD’) |
OrderDesc | boolean | Optional - Sorting order (Default set to ascending order (False)) |
Response
Field | Datatype | Description |
---|---|---|
ErrorStatus | number | 0 if OK, error code otherwise. |
SendingTime | number | Unix timestamp with nanosecond precision. |
Result | array(object) | [{ OrdID: string, Account: string, ClOrdID: string, TransactTime: number (Unix timestamp w/ ns precision), OrdType: string ('LIMIT' or 'MARKET'), OrdStatus: string ('FILLED', 'PARTIALLY_FILLED', 'CANCELLED', or 'ORDER_REJECTED'), TimeInForce: string ('FILL_OR_KILL' or 'IMMEDIATE_OR_CANCEL'), Symbol: string (e.g. 'BTC-USD'), Side: string ('BUY' or 'SELL'), OrderQty: number, Price: number, LastPx: number, LastQty: number, LeavesQty: number, CumQty: number, AvgPx: number, Text: string ('Filled' or cancel reason) },...] |
Text | string | ‘Success’ or reason for error |
Balance Status
import requests
payload = ""
url = "https://<trading-api-url>/balanceStatus?APIKEY=11213&PAYLOAD="+ payload +"&NONCE=1634241864011000000&SIGNATURE=91f0bb5c89b01235ded238b82f9613cdeeb76bf8d1f15470890927a684b2bea0e4fa08b4bc628a67434b4c8cb37e355a"
response = requests.request("POST", url, headers=headers)
The above command returns JSON structured like this:
{
"ErrorStatus": 0,
"SendingTime": 1634648211947571440,
"Result": [
{
"Symbol": "ADA-USD",
"Qty": 67.473386
},
{
"Symbol": "BTC-USD",
"Qty": 103.01804763
},
{
"Symbol": "ETH-USD",
"Qty": 2884.51758661
},
{
"Symbol": "SOL-USD",
"Qty": 0.4601
},
{
"Symbol": "XLM-USD",
"Qty": 6.04
},
{
"Symbol": "USD",
"Qty": -14920863.19
}
],
"Text": "Success"
}
Obtain the outstanding quantity of unsettled trades summed by symbol. Negative balances are owed to Genesis, positive balances are owed to Client.
HTTP Request
POST https:<trading-api-url>/balanceStatus?APIKEY=KEY&PAYLOAD=PL&NONCE=NC&SIGNATURE=SIGNATURE
Arguments
None
Response
Field | Datatype | Description |
---|---|---|
ErrorStatus | number | 0 if OK, error code otherwise. |
SendingTime | number | Unix timestamp with nanosecond precision. |
Result | array(object) | [{'Symbol': string, 'Qty': number},...] e.g. [{'Symbol': 'BTC-USD', 'Qty': 3.23}] |
Text | string | ‘Success’ or reason for error |
Settlement Status
import requests
payload = ""
url = "https://<trading-api-url>/settlementStatus?APIKEY=11213&PAYLOAD="+ payload +"&NONCE=1634241864011000000&SIGNATURE=91f0bb5c89b01235ded238b82f9613cdeeb76bf8d1f15470890927a684b2bea0e4fa08b4bc628a67434b4c8cb37e355a"
response = requests.request("POST", url, headers=headers)
The above command returns JSON structured like this:
{
"ErrorStatus": 0,
"SendingTime": 1634648211947571440,
"Result": [
{
"Symbol": "ADA-USD",
"Qty": 67.473386
},
{
"Symbol": "BTC-USD",
"Qty": 103.01804763
},
{
"Symbol": "ETH-USD",
"Qty": 2884.51758661
},
{
"Symbol": "SOL-USD",
"Qty": 0.4601
},
{
"Symbol": "XLM-USD",
"Qty": 6.04
},
{
"Symbol": "USD",
"Qty": -14920863.19
}
],
"Text": "Success"
}
Obtain the outstanding set of settlement batches with creation times. Negative balances are owed to Genesis, positive balances are owed to Client.
In the example below, Client would settle by sending 1.45 BTC to Genesis and would receive 16032 USD from Genesis.
HTTP Request
POST https:<trading-api-url>/settlementStatus?APIKEY=KEY&PAYLOAD=PL&NONCE=NC&SIGNATURE=SIGNATURE
Arguments
Argument | Datatype | Description |
---|---|---|
StartTime | number | Optional - Unix timestamp with nanosecond precision, else 0 for beginning of time |
EndTime | number | Optional - Unix timestamp with nanosecond precision (must be > StartTime) |
Limit | number | Optional - Number of orders (Default set to 20, otherwise 1 <= Limit <= 100) |
OrderDesc | boolean | Optional - Sorting order (Default set to ascending order (False)) |
Response
Field | Datatype | Description |
---|---|---|
ErrorStatus | number | 0 if OK, error code otherwise. |
SendingTime | number | Unix timestamp with nanosecond precision. |
Result | array(object) | [{ BatchID: number, CreateTime: number (Unix timestamp w/ ns precision), Status: string ('PENDING' or 'SETTLED'} Balances: [{'Symbol': string, 'Qty': number},...]},...] e.g. [{ BatchID: 601, CreateTime: 1610390686000000000, Status: 'SETTLED', Balances: [{'Symbol': 'BTC-USD', 'Qty': -1.45}, {'Symbol': 'USD', 'Qty': 50032.21}] }] |
Text | string | ‘Success’ or reason for error |
Stream
import requests
payload = {"ClOrdId":"576048115236807"}
url = "https://<trading-api-url>/orderStatus?APIKEY=11213&PAYLOAD="+ payload +"&NONCE=1634241864011000000&SIGNATURE=91f0bb5c89b01235ded238b82f9613cdeeb76bf8d1f15470890927a684b2bea0e4fa08b4bc628a67434b4c8cb37e355a"
response = requests.request("POST", url, headers=headers, data=payload)
The above command returns JSON structured like this:
{
"ErrorStatus": 0,
"SendingTime": 1635307485199219381,
"Result": [
{
"OrdID": "8374283749237498273",
"Account": "key",
"ClOrdID": "128371827481827",
"TransactTime": 1635307481965122901,
"OrdType": "MARKET",
"OrdStatus": "FILLED",
"TimeInForce": "FILL_OR_KILL",
"Symbol": "BTC-USD",
"Side": "BUY",
"OrderQty": 0.01,
"Price": 0,
"LastPx": 61006.46,
"LastQty": 0.01,
"LeavesQty": 0,
"CumQty": 0.01,
"AvgPx": 61006.46,
"Text": "Filled"
}
],
"Text": "Success"
}
Receive live Level II market data updates and trade events as carriage-return new line “\r\n”
delimited JSON. Decode an object by looking at the “Type” key.
Market Data Subscription
To see L2 quotes for a given symbol, please submit a successful subscription request via the /marketDataRequest endpoint.
Number of Connections
Only one streaming connection is allowed per client API key. Additional connection attempts will be closed by the host and return with REST error: “Stream active”.
Number of Levels
The number of levels streamed to the client will be determined by the Genesis Trading Desk prior to trading in production.
Field Descriptions
The price and quantity fields of the execution report for a given order is in accordance with FIX specifications.
HTTP Request
GET https:<trading-api-url>/stream?APIKEY=KEY&PAYLOAD=PL&NONCE=NC&SIGNATURE=SIGNATURE
Arguments
None
Response
Streaming JSON. EOF denotes finalization of request and pending closure of socket connection.
Field | Datatype | Description |
---|---|---|
SequenceNumber | number | Session-dependent monotonically increasing sequence number. Resets upon disconnect/logout. |
Result | object | [{'Type': string, 'Data': object},...] Type: 'ExecutionReport' (fill, partial fill, cancel, or reject) { OrdID: string, Account: string, ClOrdID: string, TransactTime: number (Unix timestamp w/ ns precision), OrdType: string ('LIMIT' or 'MARKET'), OrdStatus: string ('FILLED', 'PARTIALLY_FILLED', 'CANCELLED', or 'ORDER_REJECTED'), TimeInForce: string ('FILL_OR_KILL' or 'IMMEDIATE_OR_CANCEL'), Symbol: string (e.g. 'BTC-USD'), Side: string ('BUY' or 'SELL'), OrderQty: number, Price: number, LastPx: number, LastQty: number, LeavesQty: number, CumQty: number, AvgPx: number, Text: string ('Filled' or cancel reason) } Type: 'L2Update' (order book change) { Venue: 'GENESIS', QuoteTime: number (Unix timestamp w/ ns precision), ValidUntil: number (Unix timestamp w/ ns precision), Symbol: string, Changes 2: [{‘Entry’: [string number number]}, {‘Entry’: [string number number]},...] e.g. [{‘Entry’: ['BUY' price qty]}, {‘Entry’: ['BUY' price qty]} {‘Entry’: ['SELL' price qty]} {‘Entry’: ['SELL' price qty]},...] } |
Text | string | ‘Success’ or reason for error |
MetaData
import requests
url = "https://<trading-api-url>/metadata?APIKEY=11213&PAYLOAD=null&NONCE=1634241864011000000&SIGNATURE=91f0bb5c89b01235ded238b82f9613cdeeb76bf8d1f15470890927a684b2bea0e4fa08b4bc628a67434b4c8cb37e355a"
payload = ""
response = requests.request("POST", url, headers=headers, data=payload)
The above command returns JSON structured like this:
{
"ErrorStatus": 0,
"SendingTime": 1632932203993892508,
"Result": {
"Instruments": {
"BSV-USD": {
"Qtys": [
0.5,
5,
35
],
"Enabled": true
},
"BTC-USD": {
"Qtys": [
0.5,
5,
35
],
"Enabled": true
},
"ZEC-USD": {
"Qtys": [
0.1,
0.2,
1
],
"Enabled": false
}
},
"Enabled": true,
"MaxNotionalDayDollars": 1000000000,
"MaxNotionalOrderDollars": 1000000000,
"RefreshIntervalDurationSecs": 10
},
"Text": "Success"
}
Configuration information including notional risk limits (in USD) and quoting parameters.
HTTP Request
POST https:<trading-api-url>/metadata?APIKEY=KEY&PAYLOAD=PL&NONCE=NC&SIGNATURE=SIGNATURE
Arguments
None
Response
Field | Datatype | Description |
---|---|---|
ErrorStatus | number | 0 if OK, error code otherwise. |
SendingTime | number | Unix timestamp with nanosecond precision. |
Result | array (object) | [{ QuoteFrequencyMs: number, MaxDayNotionalDollars: number, MaxDayNotionalOrderDollars: number, Instruments: {{Symbol: {Enabled: bool, Qty: [number]}}, {Symbol: {Enabled: bool, Qty: [number]}} e.g. {{BTC-USD: {Enabled: True, Qty: [10]}}, {ETH-USD: {Enabled: False, Qty: [50]}} }] |
Text | string | ‘Success’ or reason for error |
Logout
import requests
url = "https://<trading-api-url>/logout?APIKEY=11213&PAYLOAD=null&NONCE=1634241864011000000&SIGNATURE=91f0bb5c89b01235ded238b82f9613cdeeb76bf8d1f15470890927a684b2bea0e4fa08b4bc628a67434b4c8cb37e355a"
payload = ""
response = requests.request("POST", url, headers=headers, data=payload)
The above command returns JSON structured like this:
{
"ErrorStatus": 0,
"SendingTime": 1634662115368273207,
"Result": null,
"Text": "Success"
}
Cleanly teardown the streaming URL, unsubscribing from any active market data requests. The streaming URL should send a logout message as the final message before finalizing the HTTP request (sending EOF) and closing the socket.
HTTP Request
POST https:<trading-api-url>/logout?APIKEY=KEY&PAYLOAD=PL&NONCE=NC&SIGNATURE=SIGNATURE
Arguments
None
Response
Field | Datatype | Description |
---|---|---|
ErrorStatus | number | 0 if OK, error code otherwise. |
SendingTime | number | Unix timestamp with nanosecond precision. |
Result | null | null |
Text | string | ‘Success’ or reason for error |
Appendix
Error Text
Endpoint(s) | Error | Text |
---|---|---|
All | Client exceeds rate limits | Rate limit exceeded, please try again later |
Missing arguments in request | Missing required arguments:{comma separated list of missing arguments} | |
Unsupported argument in request | Unsupported argument provided in {client requested arguments} | |
Invalid API Key length | Invalid API key length, expected 50 max length but got {client api key length} instead | |
Invalid payload length | Invalid payload length, expected 100000 max length but got {client payload length} instead | |
Invalid nonce length | Invalid nonce length, expected 19 max length but got {client nonce length} instead | |
Expired nonce | Expired nonce: nonce: {client requested nonce} expired {time since requested nonce expiry} ago | |
All endpoints with no required arguments | Non-null payload | Non-null payload sent |
/marketDataRequest | Invalid action | Invalid action sent, please send SUBSCRIBE |
No valid symbols sent | Invalid symbols sent, please call /securityDefinitionRequest for list of valid symbols and /metadata for enabled symbols | |
/quote | Not subscribed to market data | Quote not found, please subscribe to market data |
/newOrderSingle | Invalid symbol | Invalid symbol sent, please call /securityDefinitionRequest for list of valid symbols |
Invalid ClOrdID | Invalid ClOrdID sent, please check length and characters in ClOrdID | |
Invalid OrdType | Invalid OrdType sent, please send either LIMIT or MARKET | |
Invalid TIF | Invalid TimeInForce sent, please send either FILL_OR_KILL or IMMEDIATE_OR_CANCEL | |
Invalid side | Invalid side sent, please send either BUY or SELL | |
Invalid limit price | Invalid price sent, please ensure price is positive and within precision limits | |
Invalid order qty | Invalid order qty sent, please ensure order qty is positive and within precision limits | |
IOC market order | Invalid order, MARKET order must be FILL_OR_KILL | |
Duplicate ClOrdID | Duplicate ClOrdID sent, please ensure ClOrdIDs are unique | |
Client not enabled for symbol | Invalid symbol sent, please call /metadata for list of enabled symbols | |
/tradeHistory | Invalid time range | Invalid time range sent, please ensure start time and end time are positive and start time < end time |
Invalid pagination limit | Invalid pagination limit sent, please ensure 0 <= Limit <= 100 | |
Invalid side | Invalid side sent, please send BUY, SELL or an empty string | |
Invalid symbol | Invalid symbol sent, please either populate symbol as an empty string or call /securityDefinitionRequest for list of valid symbols to populate | |
/orderStatus | Invalid ClOrdID | Invalid ClOrdID sent, please check length and characters in ClOrdID |
Order Rejects & Cancels
Endpoint(s) | Error | Text |
---|---|---|
Reject | Client not enabled for trading | Not enabled for trading |
Client not enabled to trade instrument | Not enabled for trading this instrument | |
Internal Server Error | Internal Server Error | |
Client order notional limit exceeded | Order notional limit exceeded | |
Client daily notional limit exceeded | Daily notional limit exceeded | |
Client not subscribed to market data | Must subscribe to market data before placing order | |
Cancel | Pricing failure | Insufficient liquidity |
Limit condition failure | Out-of-limit price. | |
FOK Matching failure - no matches | No fills | |
Unable to fill entire quantity | FOK - order quantity greater than available inventory | |
IOC Matching failure - no matches | No fills |