EMS - Starter Guide
This section will provide general information about the Execution Management System API (EMS API
) software product and enumerate a number of features that it provides.
What is EMS API?
Execution Management System (EMS) is a software that managing orders, executions and exposure in an efficient, fast, cost-effective, and straightforward manner. An EMS allows you to route orders to multiple cryptocurrency exchanges simultaneously using a simple, robust, and unified Application Programming Interface (API).
Software can be used in 2 different ways:
Managed Cloud
- Everything on our side. Hosted in the Cloud by CoinAPI. You manage the deployment using the REST API.Self Hosted
- Software on our side, on your everything else.
Dimension Comparison | Managed Cloud | Self Hosted |
---|---|---|
Ease of use/installation | Very easy | Hard |
Time to market | Fast | Slow |
DevOps team required to maintain | No | Yes |
Order-flow sent directly to the destination | No | Yes |
Who manage the infrastructure (incl. monitoring) | CoinAPI | You |
Who optimize the latency | CoinAPI | You (CoinAPI only in software) |
How to install | Instruct our Cloud Mgmt API | Install on your infrastructure |
Architecture and components
An self-hosted EMS cluster can be deployed on single server or multiple servers that will span multiple geographical locations, server sites or cloud providers. In the Managed Cloud version you did not care about that as we manage the server sites to be as close to the order destinations as possible.
EMS consist of several components listed and ordered by dependency relationship:
Exchange
- Order destination, exchange or broker.CoinAPI EMS Edge
- Software that's responsible for communicating with the single specific order destination for which is deployed. This component is exposing theEMS API
for diagnostics purposes which functions visibility are limited to this single destination.CoinAPI EMS API
- Software that's responsible for exposing fully functional theEMS API
, maintainitng connection with all instances ofCoinAPI EMS Edge
.CoinAPI EMS WebUI
- Web interface (GUI) to theEMS API
interface. (optional)Customer Application
- Customer software using theEMS API
exposed byCoinAPI EMS API
component.
Benefits and features
Low latency support
Specific projects usually involving High-Frequency Trading (HFT) or Market Making (MM) requiring low latency access to the order destination. EMS API
was designed to have native support for this kind of activity.
For every order destination in the cluster to which the submillisecond latency is required, this components should be deployed on a single server as close as possible to the order destination:
CoinAPI EMS Edge
CoinAPI EMS API
Customer Application
Closest proximity can be achieved using the:
cloud region and/or availability zone same as the destination
collocation near the destination
cross-connect or direct-connect to the destination network infrastructure
shortcutting the routers, SNAT/DNAT hosts, or proxies like CloudFlare
The cluster can naturally contain other order destinations at the same time in this setup, and this fact doesn't affect the latency to the locally provisioned destination(s).
Normalized API abstraction
Our EMS API provides an abstraction layer that consolidates all supported third-party APIs into a single set of simple and robust data models and protocols. The Exchanges and the Assets are standardized using the Market Data REST API to which this product is compatible. More information about the exchanges and assets standardization can be found in the Documentation of the Market Data Product.
Industry standard protocols
Our API's can be accessed using multiple protocols widely adopted by the industry as a standard:
REST
WebSocket
FIX 4.4, 5.0
FIXT 1.1
Self-host or in Cloud
Deploy your property applications and trading algorithms in your company collocated data centers or cloud providers if you need that, otherwise let us manage the infrasturcture and focus on using the API.
Security & Privacy
Don't need to worry about the issues at the audit. Order flow, exchange API keys, or execution reports are never leave your company infrastructure as the product is self-hosted.
Multi account support
Manage unlimited number exchange accounts in the cluster (for example, on behalf of your customers).
SDK and samples for 40+ languages
We have the SDK libraries and code samples available for more than 40+ languages. Full list is available here: https://github.com/coinapi/coinapi-sdk/tree/master/oeml-sdk
Comprehensive support
Leverage support for all market types and order types.
High quality integrations
Our integrations with third-party APIs are heavily tested and crafted with the stability and latency in mind. For several third parties, we usually use multiple protocols simultaneously or tricks to acquire valuable pieces of information faster.
Enterprise-grade support and maintenance
EMS product is fully supported and maintained to stay ahead of the curve. This approach offloading the often disliked responsibilities of the Software and DevOps Engineers in the organization and enables them to focus on the core business.
High availability
The EMS software is designed to support high-availability deployments out of the box. For each order destination, we/you deploy multiple CoinAPI EMS Edge
and CoinAPI EMS API
components on different servers, availability zones, or cloud/infrastructure providers. Cluster using the service discovery backend, all components are automatically detected and interconnected.
P&L and asset monitoring
Using the EMS, your organization can manage exposure and positions in real-time across all supported order destinations and build sophisticated risk management controls.
Order lifecycle
This section will describe lifecycle of the order in the EMS
sofware.
Order status description
This table describes how to interpret a specific order status.
Name | Can transit to | Status description |
---|---|---|
RECEIVED |
REJECTED ROUTING |
The order is processed by the EMS . |
ROUTING |
ROUTED |
The order is (on the wire) between the EMS and the Exchange . |
ROUTED |
REJECTED NEW PARTIALLY_FILLED FILLED CANCELED |
The order has been sent to the exchange and not yet active in the order book. |
NEW |
PARTIALLY_FILLED FILLED PENDING_CANCEL CANCELED |
The order is active in the book in its original state. |
PENDING_CANCEL |
NEW PARTIALLY_FILLED FILLED CANCELED |
The order cancelation message has been sent to the Order destination . |
PARTIALLY_FILLED |
FILLED PENDING_CANCEL CANCELED |
The order is partially filled and active in the order book. |
FILLED |
The order is filled and removed from the order book. This state is terminal. | |
CANCELED |
The order is canceled and removed from the order book. This state is terminal. | |
REJECTED |
The order is rejected. This state is terminal. |
Order status lifecycle
This table describes how to interpret transitions between order statuses and their initial values.
Source Status | Destination status | Description |
---|---|---|
RECEIVED |
EMS received a new order via the API. |
|
NEW |
EMS received an unseen new order from the Order destination . The order was relayed to the destination outside the EMS . |
|
PARTIALLY_FILLED |
EMS received unseen partially filled order from the Order destination . The order was relayed to the destination outside the EMS . |
|
RECEIVED |
REJECTED |
EMS rejected the order. |
RECEIVED |
ROUTING |
EMS delivering the order to the Order destination . |
ROUTING |
ROUTED |
EMS sent the order to the Order destination . |
ROUTED |
REJECTED |
EMS received a message from the exchange that the order was rejected. |
ROUTED |
NEW |
EMS received a message from the exchange that the order is active in the book in its original state. |
ROUTED |
PARTIALLY_FILLED |
EMS received a message from the exchange that part of the order was executed aggressively (removed liquidity). The remaining passive part is active in the book. |
ROUTED |
FILLED |
EMS received a message from the exchange that the order was executed aggressively (removed liquidity). |
ROUTED |
CANCELED |
EMS received a message from the exchange that the order is in the canceled state. The order has not been in the book as the conditions for the entry were not satisfied. |
NEW |
PARTIALLY_FILLED |
EMS received a message from the exchange that part of the passive order was filled. |
NEW |
FILLED |
EMS received a message from the exchange that the passive order is filled. |
NEW |
PENDING_CANCEL |
EMS received cancel request for the order and successfully relayed it to the Order destination . |
NEW |
CANCELED |
EMS received a message from the exchange that the passive order was canceled. |
PARTIALLY_FILLED |
FILLED |
EMS received a message from the exchange that the remaining part of the passive order is filled. |
PARTIALLY_FILLED |
PENDING_CANCEL |
EMS received cancel request for the remaining part of the passive order and successfully relayed it to the Order destination . |
PARTIALLY_FILLED |
CANCELED |
EMS received a message from the exchange that the remaining part of the passive order is canceled. |
PENDING_CANCEL |
NEW |
EMS received a message from the exchange that updated the order before processing the cancellation request or the order cancellation request was rejected. |
PENDING_CANCEL |
PARTIALLY_FILLED |
EMS received a message from the exchange that updated the order before processing the cancellation request or the order cancellation request was rejected. |
PENDING_CANCEL |
FILLED |
EMS received a message from the exchange that updated the order before processing the cancellation request or the order cancellation request was rejected. |
PENDING_CANCEL |
CANCELED |
EMS received a message from exchange` that updated the order before processing the cancellation request or the order cancellation request was rejected. |
Order parameters
This section will describe parameters of the order in the EMS
sofware.
Order type
EMS
supports only the LIMIT
order type. Market orders don't have price protection, and because of that, they are not supported. As an alternative, you can use the Immediate or Cancel IOC
order and provide the worst execution price to achieve the same result.
Time in force
Time in force is a special instruction used when placing a trade to indicate how long an order will remain active before it expires.
The table below describes how to interpret time in force parameter values.
Time in force | Shortcode | Description |
---|---|---|
GOOD_TILL_CANCEL |
GTC |
A Good Till Cancel (GTC) is a default type of time-in-force. The order that lasts until is completed or canceled. |
GOOD_TILL_TIME_EXCHANGE |
GTTE |
The Good Till Time Exchange (GTTE) time in force lets you set an expiration date and time up until which an order will be active in the book. The exchange handles the execution of the cancel originated from parameter. |
GOOD_TILL_TIME_OEML |
GTTO |
The Good Till Time OEML (GTTO) time in force lets you set an expiration date and time up until which an order will be active in the book. The CoinAPI EMS Edge sending the cancel request originated from the parameter. Worth mentioning that: (a) The cancellation request will not be sent if the software will be not be running at the time of expiration. (b) This parameter does not depend on the exchange. (c) The clock of the server running CoinAPI EMS Edge is used to trigger the cancelation request at the expiration. |
FILL_OR_KILL |
FOK |
Fill or kill (FOK) is a type of time in force used to instruct an exchange to execute a transaction immediately and completely or not at all. This order will only remove liquidity from the order book. It must be filled in its entirety or canceled (killed). |
IMMEDIATE_OR_CANCEL |
IOC |
An immediate or cancel order (IOC) is a type of time in force used to instruct an exchange to execute all or part immediately and cancels any unfilled portion of the order. This order will only remove liquidity from the order book. It will fill whatever part of the order it can immediately and cancel any remaining amount so that no part of the order is added to the order book. |
The table below displays a breakdown of the EMS
support of specific time in force values by the Order destination
.
Order destination id | GTC |
GTTE |
GTTO |
FOK |
IOC |
---|---|---|---|---|---|
BINANCE | X | X | X | X | |
BINANCEUAT | X | X | X | X | |
BINANCEJE | X | X | X | X | |
BINANCEUS | X | X | X | X | |
BINANCEFTS | X | X | X | X | |
BINANCEFTSUAT | X | X | X | X | |
BINANCEFTSC | X | X | X | X | |
BINANCEFTSCUAT | X | X | X | X | |
BINANCEOPTV | X | X | X | X | |
BINANCEOPTVUAT | X | X | X | X | |
BITFINEX | X | X | X | X | X |
BITMEX | X | X | X | X | |
BITMEXUAT | X | X | X | X | |
BITSTAMP | X | X | X | X | |
BLOCKCHAINEXCHANGE | X | X | X | X | |
COINBASE | X | X | X | X | |
GEMINI | X | X | X | X | |
HITBTC | X | X | X | X | X |
KRAKEN | X | X | X | ||
KRAKENFTS | X | X | X | ||
POLONIEX | X | X | X | X | |
LMAXDIGITAL | X | X | X | X | |
LMAXDIGITALUAT | X | X | X | X | |
FTX | X | X | X | ||
FTXUS | X | X | X | ||
DERIBIT | X | X | X | X | |
DERIBITUAT | X | X | X | X |
Legend: X
- supported.
Execution instructions
Execution instruction puts restrictions on order handling at the matching engine. More than one instruction can apply to an order. The table below describes how to interpret execution instructions parameter values. Legend: X
- supported.
Instruction | Shortcode | Description |
---|---|---|
AUCTION_ONLY |
AO |
An Auction Only (AO) instructs exchange that this order is for the auction only book for the next auction. The order may be cancelled up until the the auction locks, after which cancel requests will be rejected. |
INDICATION_OF_INTEREST |
IOI |
An indication of interest (IOI) instructs exchange that this order should be processed as request for liquidity from block trading market markets. |
MAKER_OR_CANCEL |
MOC |
A Maker or cancel (MOC) instructs exchange that this order will only add liquidity to the order book. If any part of the order could be filled immediately, the whole order will instead be rejected before any execution occurs. This instruction is also known as Post only or Participate don't initiate . |
CANCEL_ON_DISCONNECT |
COD |
Cancel on System Failure (Cancel on disconnect) |
DO_NOT_CANCEL_ON_DISCONNECT |
NCOD |
Reinstate on System Failure (Do not cancel on disconnect) |
DO_NOT_INCREASE |
DNI |
(Reduce only) If part of a position is closed by any other means than the reduce-only order, the reduce-only order will be automatically adjusted downwards. If the trader decides to increase their position before the reduce-only order is executed, the quantity of the reduce-only order will not increase as well. |
The table below displays a breakdown of the EMS
support of specific execution instructions by the Order destination
.
Order destination id | MOC |
AO |
IOI |
COD |
NCOD |
DNI |
---|---|---|---|---|---|---|
BINANCE |
X | |||||
BINANCEUAT |
X | |||||
BINANCEJE |
X | |||||
BINANCEUS |
X | |||||
BINANCEFTS |
X | |||||
BINANCEFTSUAT |
X | |||||
BINANCEFTSC |
X | |||||
BINANCEFTSCUAT |
X | |||||
BINANCEOPTV |
X | |||||
BINANCEOPTVUAT |
X | |||||
BITFINEX |
X | |||||
BITMEX |
X | |||||
BITMEXUAT |
X | |||||
BITSTAMP |
||||||
BLOCKCHAINEXCHANGE |
X | |||||
COINBASE |
X | |||||
GEMINI |
X | X | X | |||
HITBTC |
||||||
KRAKENFTS |
X | |||||
KRAKEN |
X | |||||
POLONIEX |
X | |||||
LMAXDIGITAL |
X | X | ||||
LMAXDIGITALUAT |
X | X | ||||
FTX |
X | X | ||||
FTXUS |
X | X | ||||
DERIBIT |
X | X | ||||
DERIBITUAT |
X | X |
Legend: X
- supported.
Time
For all input and output time values ISO 8601 standard is used.
Format specifier | Description |
---|---|
yyyy |
The year as a four-digit number. |
MM |
The month, from 01 through 12. |
dd |
The day of the month, from 01 through 31. |
HH |
The hour, using a 24-hour clock from 00 to 23. |
mm |
The minute, from 00 through 59. |
ss |
The second, from 00 through 59. |
fff |
The milliseconds in a date and time value. |
fffffff |
The ten millionths of a second in a date and time value. |
Input time values are parsed using the following formats as far as possible:
yyyy-MM-ddTHH:mm:ss.fffffff
yyyy-MM-ddTHH:mm:ss.fff
yyyy-MM-ddTHH:mm:ss
yyyy-MM-ddTHH:mm
yyyy-MM-ddTHH
yyyy-MM-dd
yyyyMMddTHHmmssfffffff
yyyyMMddTHHmmssfff
yyyyMMddTHHmmss
yyyyMMddTHHmm
yyyyMMddTHH
yyyyMMdd
Output time values are formatted using the following patterns:
yyyy-MM-ddTHH:mm:ss.fffffffZ
yyyy-MM-dd
EMS - Self Hosted Guide
This section will provide information related to self-hosted deployment of Execution Management System API (EMS API
) software.
Configuration Manual
This section will provide the necessary information how to configure the CoinAPI EMS
software.
Configuration keys and values
Configuration keys:
Are case-insensitive. For example,
ExchangeId
andexchangeid
are treated as equivalent keys.If a key and value is set in more than one configuration providers, the value from the last provider added is used.
Using array indices in configuration keys are allowed.
Hierarchical keys
- Within the Configuration API, a colon separator (
:
) works on all platforms. - In environment variables, a colon separator may not work on all platforms. A double underscore,
__
, is supported by all platforms and is automatically converted into a colon:
.
- Within the Configuration API, a colon separator (
Configuration values:
Are strings.
Null values can't be stored in configuration.
Configuration providers
You can set the values of configuration parameters for the components using the following providers (in case of collision for any specific key):
Command-line arguments
Environment variables
Environment variables
To configure specific parameters using host or container environment variable, you must replace all occurrences of :
with __
in the configuration parameter key, this is because the :
separator doesn't work with environment variable hierarchical keys on all platforms. __
, the double underscore, is:
Supported by all platforms. For example, the
:
separator is not supported by Bash, but__
is.Automatically replaced by a
:
For example, to set the value of the configuration parameter OEML:ExchangeId
to BITSTAMP
you would need to set the environment variable named OMS__ExchangeId
to BITSTAMP
.
Command-line arguments
You can set the configuration parameters by providing the arguments to the application executable.
The following example sets keys and values using the =
: OEML:ExchangeId=BITSTAMP
The following example sets keys and values using the /
: /OEML:ExchangeId=BITSTAMP
The following example sets keys and values using the --
: --OEML:ExchangeId=BITSTAMP
or --OEML:ExchangeId BITSTAMP
The key value:
Must follow
=
, or the key must have a prefix of--
or/
when the value follows a space.Isn't required if
=
is used. For example,MySetting=
.
Within the same command, don't mix command-line argument key-value pairs that use = with key-value pairs that use a space.
Configuration parameters
Key | Type | Description | Is Required? | Default value |
---|---|---|---|---|
OEML:ServiceDiscoveryMode | string | Type of backend used for service discovery. Supported values: COINAPI or CONSUL |
No | COINAPI |
OEML:LocalAddress | string | Override the local IP address advertised to other components. The value of this parameter is used in the CoinAPI Service Discovery mode. The API is listening to all the IP addresses available. However, the software still needs a valid single IP address accessible to other components, we will use this address for advertising in the CoinAPI Service Discovery mode only. | No | IP of the first IPv4 network interface. |
OEML:Port | int | Set the TCP Port for REST and WebSocket API. | No | Randomly selected free port. |
OEML:FIX:SocketAcceptPort | int | FIX Acceptor/Server Port | No | 3401 |
OEML:ExchangeId | string | Exchange identifier and optional tag identifying specific account configured when the software will be managing multiple accounts on the same exchange; for eg:BITSTAMP BITSTAMP/7c177641-74bd-4dbe-9b01-2497c12a5f70 BITSTAMP/2574 . Allowed separators between the exchange identifier and the tag: ~/.,:;\[email protected]#$%^&*-_+= . |
Yes | |
CoinAPI:ApiKey | string | CoinAPI API Key | Yes | |
CoinAPI:UrlRest | string | CoinAPI REST API Endpoint | No | https://rest.coinapi.io/ |
CoinAPI:RatesUpdateIntervalSeconds | int | Update interval of the exchange rates in seconds from CoinAPI (using /v1/exchangerate/USD endpoint). 0 mean that rates will be pulled just on startup once, and -1 mean that they will not be downloaded at all. |
No | 3600 |
OD:PublicApiKey | string | Customer Public Key for the Exchange | Conditionally | |
OD:PrivateApiKey | string | Customer Private Key for the Exchange | Conditionally | |
OD:PassPhrase | string | Customer passphrase for the Exchange | Conditionally | |
OD:CustomerId | string | CustomerId of customer exchange account | Conditionally | |
OD:Username | string | Exchange client username | Conditionally | |
OD:Password | string | Exchange client password | Conditionally | |
OD:Host | string | Exchange API endpoint host | Conditionally | |
OD:Port | int | Exchange API endpoint port | Conditionally | |
OD:RestApiUrl | string | Exchange REST API Url | Conditionally |
Exchange conditional parameters
The table below explains the conditional parameters by the OEML:ExchangeId value.
For example when OEML:ExchangeId == "BITSTAMP"
then OEML:Exchanges:BITSTAMP:CustomerId
is required.
OEML:ExchangeId | Required parameters | Optional parameters |
---|---|---|
BINANCE | OD:PublicApiKey OD:PrivateApiKey | |
BINANCEJE | OD:PublicApiKey OD:PrivateApiKey | |
BINANCEUS | OD:PublicApiKey OD:PrivateApiKey | |
BINANCEUAT | OD:PublicApiKey OD:PrivateApiKey | |
BINANCEFTS | OD:PublicApiKey OD:PrivateApiKey | |
BINANCEFTSUAT | OD:PublicApiKey OD:PrivateApiKey | |
BINANCEFTSC | OD:PublicApiKey OD:PrivateApiKey | |
BINANCEFTSCUAT | OD:PublicApiKey OD:PrivateApiKey | |
BINANCEOPTV | OD:PublicApiKey OD:PrivateApiKey | |
BINANCEOPTVUAT | OD:PublicApiKey OD:PrivateApiKey | |
BITFINEX | OD:PublicApiKey OD:PrivateApiKey | |
BITMEX | OD:PublicApiKey OD:PrivateApiKey | |
BITMEXUAT | OD:PublicApiKey OD:PrivateApiKey | |
BITSTAMP | OD:PublicApiKey OD:PrivateApiKey OD:CustomerId | |
BLOCKCHAINEXCHANGE | OD:PublicApiKey OD:PrivateApiKey | |
COINBASE | OD:PublicApiKey OD:PrivateApiKey OD:PassPhrase | OD:Host OD:RestApiUrl |
GEMINI | OD:PublicApiKey OD:PrivateApiKey | |
HITBTC | OD:PublicApiKey OD:PrivateApiKey | |
KRAKENFTS | OD:PublicApiKey OD:PrivateApiKey | |
KRAKEN | OD:PublicApiKey OD:PrivateApiKey | |
POLONIEX | OD:PublicApiKey OD:PrivateApiKey | |
LMAXDIGITAL | OD:Username OD:Password OD:Host OD:Port | |
LMAXDIGITALUAT | OD:Username OD:Password OD:Host OD:Port | |
FTX | OD:PublicApiKey OD:PrivateApiKey | OD:Host OD:Port OD:RestApiUrl |
FTXUS | OD:PublicApiKey OD:PrivateApiKey | OD:Host OD:Port OD:RestApiUrl |
DERIBIT | OD:ClientId OD:ClientSecret | OD:Host OD:Port |
DERIBITUAT | OD:ClientId OD:ClientSecret | OD:Host OD:Port |
Exchange specific recommendations
Kraken Futures KRAKENFTS
Whitelist your IP addresses
Whitelisting your IP addresses will give you the lowest possible latency and most stable connection to exchange servers in AWS EU-West 1. Whitelisting works by allowing you to skip CloudFlare. Here is an article on how to whitelist your IP addresses.
Consul Configuration (optional)
The end result should look like this:
{
"datacenter": "hq",
"data_dir": "C:\\consul\\data-hq",
"log_level": "INFO",
"server": false,
"retry_join": [ "server-a", "server-b", "server-c" ],
"ui": true,
"http_config": {
"response_headers": {
"Access-Control-Allow-Origin": "*"
}
}
}
If your deployment including optional Consul Cluster for the Service Discovery layer then it's required to change CORS
settings of the local Consul client on the hosts where the EMS WebUI
will be used. This step is necessary as we need to discover the address of the EMS API
component.
"http_config": {
"response_headers": {
"Access-Control-Allow-Origin": "*"
}
}
Installation Manual
This section will provide the necessary information how to install the CoinAPI EMS software.
Service discovery
The CoinAPI EMS API
is capable of automaticaly detecting all your instances of CoinAPI EMS Edge
service. This service discovery works by the one of the following methods:
Using the
CoinAPI EMS Central Cloud
, every time you startCoinAPI EMS Edge
, it will register automatically in our central cloud infrastructure.Using the
HashiCorp Consul Cluster
.
Using the CoinAPI EMS Central Cloud
is a default, simple, and straightforward method. Only one disadvantage of using the CoinAPI EMS Central Cloud
over Consul Cluster
is that we do not measure the latencies if one order destination is registered more than one time in the cluster for failover scenarios. Then CoinAPI EMS Central Cloud
will connect to the last started exchange; however, when using the Consul Cluster
, it will connect to the order destination in the closest proximity data center to the datacenter where CoinAPI EMS API
is run.
Running using an executable
To install the precompiled binary, download the latest version of the executable matching your system architecture from http://coinapi-releases.s3-website-us-east-1.amazonaws.com/
Our software is currently packaged as a zip file, and we currently do not plan to distribute it another way. Once the zip is downloaded, unzip it into any directory. The self-contained binary inside is necessary to run EMS, and any additional files are not required to run the software.
If you intend to access it from the command-line, make sure to place the binary somewhere on your PATH
. You may require to add the executable to the system startup with all necessary parameters if you want the software to be started automatically after restart.
Running on Docker
# example using only command line parameters
docker run -d --name=HITBTC --restart=always --net=host coinapi/oeml-api --OEML:ExchangeId HITBTC \
--OD:PublicApiKey _public_api_key_ --OD:PrivateApiKey _private_api_key_ \
--CoinAPI:ApiKey _coinapi_api_key_
docker run -d --restart=always --net=host coinapi/oeml-webui
docker run --net=host coinapi/oeml-cli
# example with enviroment variables file
cat > oeml.env << EOF
CoinAPI__ApiKey=_coinapi_api_key_
OD__PublicApiKey=_public_api_key_
OD__PrivateApiKey=_private_api_key_
EOF
docker run -d --name=HITBTC --restart=always --net=host coinapi/oeml-api --env-file oeml.env --OEML:ExchangeId HITBTC
docker run -d --name=BITFINEX --restart=always --net=host coinapi/oeml-api --env-file oeml.env --OEML:ExchangeId BITFINEX
docker run -d --name=OEML_EDGE --restart=always --net=host coinapi/oeml-api --env-file oeml.env
Our software is listed in public docker repository. To run the software on docker, use the following images:
coinapi/oeml-api
coinapi/oeml-cli
coinapi/oeml-webui
To pass the configuration parameters using the environment variables (more information about this feature is available in the Configuration Manual section of this documentation), the environment variables must be provided into the container and not set on the host machine.
It's a good practice to lock itself into the specific version. To do that you can supply the version after image name and :
separator, e.g. coinapi/oeml-api:1.1255
Running on Kubernetes Cluster
Our software is compatible with Kubernetes, and you can quickly run it on the cluster using our (Helm Charts)[https://github.com/coinapi/helm-charts]. Follow steps below to perform quickstart deployment.
Add the Repository to Helm
$ helm repo add coinapi-charts https://coinapi.github.io/helm-charts/
$ helm repo update
Helm chart configuration
The example config below will create two api pods, a composite pod, and a webui pod. One exchange account corresponds to one entry in the values.yaml file. That means, for multiple exchange accounts, please add one config entry with the matching API keys for each account i.e. binance-01, binance-02, kraken-01, kraken-02, etc. A complete list of all supported exchanges can be found in the API documentation.
cat > values.yaml << EOF
# Using WebUI (oeml-api/values.yaml)
webUI:
enabled: true
# Using composite (oeml-api/values.yaml)
oemlCompositeAPI:
enabled: true
# Setting the CoinAPI key (oeml-api/values.yaml)
extraEnv:
- name: CoinAPI__ApiKey
value: "YOUR_COINAPI_APIKEY"
# Specify listing of the accounts that EMS should manage (oeml-api/acct-dev.yaml)
accounts:
# Binance spot market
- name: "binance"
env:
- name: OEML__ExchangeId
value: "BINANCE"
- name: OD__PublicApiKey
value: "XXX"
- name: OD__PrivateApiKey
value: "YYY"
# Binance spot testnet
- name: "binanceuat"
env:
- name: OEML__ExchangeId
value: "BINANCEUAT"
- name: OD__PublicApiKey
value: "XXX"
- name: OD__PrivateApiKey
value: "YYY"
EOF
Install ems-api latest version
$ helm install oeml-api coinapi-charts/oeml-api -f values.yaml
Install ems-api custom version
Version listing available here.
$ helm install oeml-api coinapi-charts/oeml-api -f values.yaml --set oemlAPI.tag={version}
Verify installation
kubectl get pods | grep oeml
Expected output:
oeml-api-binance-7754fc95cc-x2gkk 1/1 Running
oeml-api-binance-test-757c8bbd95-2mxd5 1/1 Running
oeml-api-composite-d5688f8f6-csbwh 1/1 Running
oeml-webui-685cd94d77-hq68j 1/1 Running
Inspect
Inspect binance api pod:
kubectl logs oeml-api-binance-7754fc95cc-x2gkk
Inspect testnet api pod:
kubectl logs oeml-api-binance-test-757c8bbd95-2mxd5
Expected output for both api pods:
[02:22:04 WRN] Overriding address(es) 'http://+:80'. Binding
to endpoints defined in UseKestrel() instead.
Hosting environment: Production
Content root path: /app
Now listening on: http://[::]:80
Application started. Press Ctrl+C to shut down.
List services
kubectl get svc | grep oeml
Expected output:
oeml-api-binance ClusterIP 10.112.9.119 <none> 80/TCP
oeml-api-binance-test ClusterIP 10.112.15.239 <none> 80/TCP
oeml-api-composite NodePort 10.112.8.159 <none> 80:30578/TCP
oeml-webui NodePort 10.112.4.195 <none> 80:30857/TCP
Connect to EMS API
The composite pod gives unified access to all connected exchanges & accounts. Therefore, the oeml-api-composite is the only pod required to connect to the EMS system.
Connect from within the cluster
Deploy a pod with a shell
kubectl apply -f https://k8s.io/examples/application/shell-demo.yaml
Verify the shell pod is online
kubectl get pod shell-demo
Get api-composite IP address:
kubectl get svc | grep oeml-api-composite
>oeml-api-composite NodePort 10.112.8.159
Exec into the pod
kubectl exec --stdin --tty shell-demo -- /bin/bash
CURL IP of the composite pod.
curl 10.112.8.159/v1/balances --header 'Accept: application/json'
CURL DNS of the composite pod.
DNS name may vary depending on cloud provider.
curl oeml-api-composite.default.svc.cluster.local/v1/balances --header 'Accept: application/json'
Expected output:
[
{
"type": "BALANCE_SNAPSHOT",
"exchange_id": "BINANCE",
},
{
"type": "BALANCE_SNAPSHOT",
"exchange_id": "BINANCEUAT",
"data": [
{
"id": "XRP",
"asset_id_exchange": "XRP",
"asset_id_coinapi": null,
"balance": 50000.00000000,
"available": 50000.00000000,
"locked": 0.00000000,
"traded": 0.0,
"last_updated_by": "EXCHANGE",
"rate_usd": null
},
// more entries
]
}
]
Exit the shell pod
exit
Delete shell pod
kubectl delete pod shell-demo
Connect cluster to localhost
Port-forward from cluster port 80 to localhost port 8080
kubectl port-forward service/oeml-api-composite 8080:80
Expected output:
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
CURL account balance.
curl localhost:8080/v1/balances --header 'Accept: application/json'
Expected output:
[
{
"type": "BALANCE_SNAPSHOT",
"exchange_id": "BINANCE",
},
{
"type": "BALANCE_SNAPSHOT",
"exchange_id": "BINANCEUAT",
"data": [
{
// more entries
},
]
}
]
Management Guide
This section will provide the necessary information on how to manage the CoinAPI EMS
software.
To run the EMS cluster, you will need to:
(optional) Deploy the HashiCorp Consul Cluster for Service Discovery, if you don't want or can't use our included free of charge discovery service.
Run the
CoinAPI EMS Edge
software instance per each managed exchange account.Run single or multiple instances of the
CoinAPI EMS API
software.
If the lowest latency is required, start the instance per location or server where the API will is used to minimize latency between API client and the EMS API Server
.
(optional) Run the
CoinAPI EMS WebUI
to have GUI to the cluster.Done! All the exchange accounts can be managed using the single API.
Installation
CoinAPI EMS can be installed using several approaches:
Running using an executable
Running on Docker
Running on Kubernetes Cluster
Our software is compiled for the following architectures:
- linux-x64
- linux-arm64
- osx-x64
- osx-arm64
- win-x64
- win-arm64
Take a look at the Starter Guide of this documentation for more information how to run the software in the specific conditions.
Upgrading
Currently, all components are stateless. Upgrading stateless components is limited to replacing the binaries or running the new docker image.
Versioning & Compatibility
Our software is versioned using the Major.Minor(+branch)
pattern. Major
version number is incremented manually on our side, and its scope is for the EMS project. The Minor
version number is incremented on every release automatically separately for every component.
You can assume that our software components will work together when their Major
version numbers are the same.
Time synchronization
EMS
highly depends on the current time to perform actions and correctly timestamp the data for real-time trading, risk management, compliance, or reporting.
For the time synchronization we strongly recommending:
chrony
(Linux, FreeBSD, NetBSD, Solaris, macOS)w32tm
(Windows)
If you can't use any of the programs above for reasons like:
- Software has not been ported to my operating system.
- Software doesn't have a driver or it's not compatible with my hardware reference clock, and I can't use other programs like
gpsd
orntp-refclock
to provide reference time via theSHM
orSOCK
interface.
Then it's worth trying solutions below (ordered from the best to worst options):
ntp
(Linux, FreeBSD, NetBSD, OpenBSD, Solaris, macOS, Windows)openntpd
(Linux, FreeBSD, NetBSD, OpenBSD, Solaris, macOS)
If need the sub-millisecond or sub-nanosecond accuracy take a look there:
Limits
This section will list all known software limitations.
Limit description | Limit value |
---|---|
Maximum number of managed exchange accounts in a single cluster | Unlimited |
Maximum number of managed exchange accounts per cluster host when running an executable | 65,535 |
Maximum number of managed exchange accounts per cluster node when running on Docker or Docker Swarm | 1024 |
Maximum number of managed exchange accounts per cluster node when running on Kubernetes | 250 |
Maximum number of managed exchange accounts per cluster node when running on Amazon Elastic Kubernetes Service (EKS) | from 4 to 737 |
Maximum number of managed exchange accounts per cluster node when running on Google Kubernetes Engine (GKE) | 100 |
Maximum number of managed exchange accounts per cluster node when running on Azure Kubernetes Service (AKS) | 250 |
Changelog
It's a log of: BREAKING CHANGES
, FEATURES
, IMPROVEMENTS
, BUG FIXES
or other NOTES
per public version.
2.0.12829 (March 18, 2022)
BUG FIXES:
- BITSTAMP: Exchange error info is not reported properly
2.0.12813 (March 17, 2022)
FEATURES:
- Added more detailed order debug information.
2.0.12808 (March 17, 2022)
BUG FIXES:
- BINANCE*: Balances are wiped out after placing order.
2.0.12782 (March 16, 2022)
BUG FIXES:
- BINANCE*: Exchange container can be stuck after it lost connection to the exchange.
2.0.12325 (February 25, 2022)
BUG FIXES:
- Positions in some cases could not be loaded because of the exception.
2.0.12316 (February 25, 2022)
FEATURES:
- DERIBITUAT: Added new integration.
IMPROVEMENTS:
- FTX/FTXUS: Added RestApiUrl optional parameter.
- Split parameters into conditionally required and not required.
BUG FIXES:
- DERIBITUAT: Added new integration.
- BINANCE: AvgPx and Fills data for the order was not available.
1.9281 (September 16, 2021)
FEATURES:
- POLONIEX: WebSocket balances updates added
BUG FIXES:
- POLONIEX: Order update dataflow fixes
1.9136 (September 09, 2021)
BUG FIXES:
- LMAXDIGITAL/LMAXDIGITALUAT: Added Time In Force options:
FOK
,IOC
1.9066 (August 27, 2021)
FEATURES:
- FTXUS: Added FTX.US exchange on the FTXUS identifier.
1.8931 (August 11, 2021)
FEATURES:
- Ability to control the refresh rate behaviour of exchange rates from CoinAPI trough configuration parameter.
1.8893 (August 06, 2021)
IMPROVEMENTS:
- Extended error log info on all BINANCExxx exchanges
1.8889 (August 06, 2021)
BUG FIXES:
- BINANCEOPTV/BINANCEOPTVUAT fixed invalid balance calculations
1.8877 (August 05, 2021)
FEATURES:
- BINANCEOPTV: Added BINANCE Vanilla Options exchange on the BINANCEOPTV identifier.
- BINANCEOPTVUAT: Added BINANCE Vanilla Options testnet exchange on the BINANCEOPTVUAT identifier.
1.8821 (July 29, 2021)
FEATURES:
- BINANCEFTS: Added BINANCE USDⓈ-M Futures exchange on the BINANCEFTS identifier.
- BINANCEFTSUAT: Added BINANCE USDⓈ-M Futures testnet exchange on the BINANCEFTSUAT identifier.
- BINANCEFTSC: Added BINANCE COIN-M Futures testnet exchange on the BINANCEFTSC identifier.
- BINANCEFTSCUAT: Added BINANCE COIN-M Futures testnet exchange on the BINANCEFTSCUAT identifier.
1.8797 (July 23, 2021)
IMPROVEMENTS:
- Improved order parameters validation for all exchanges
1.8787 (July 22, 2021)
BREAKING CHANGES:
- Replaced MESSAGE with MESSAGE_REJECT.
IMPROVEMENTS:
- Improved the error reporting by introducing Message Rejection.
1.8781 (July 22, 2021)
FEATURES:
- BITMEXUAT: Added BITMEX testnet exchange on the BITMEXUAT identifier.
1.8713 (July 14, 2021)
BUG FIXES:
- COINBASE/DERIBIT/FTX: Fix in the startup procedure.
- BINANCE*/BITSTAMP/KRAKEN/POLONIEX: Fixed bug that prevented multiple accounts to coexist with each other.
1.8707 (July 13, 2021)
FEATURES:
- BINANCEUAT: Added BINANCE testnet exchange on the BINANCEUAT identifier.
- BINANCE: Migrated to the /sapi from the /wapi endpoints.
- BINANCEUS: Upgraded to the v3 version of the /sapi endpoints.
IMPROVEMENTS:
- Error reporting got better when the user provided invalid parameters
- When we cant detect the local IP address then it's properly communicated
- When the CoinAPI key is a valid Guid, but not allowed to use the service then the error is more descriptive.
Integrations & Plugins
This section is reserved for Integrations, plugins or other external tools or modules that make it easier to work with EMS API
.
Prometheus metrics
In this section, we will describe the metrics exposed by the software on the /metrics endpoint.
If you are using our Helm chart then ServiceMonitor objects required by Prometheus to pull data are automatically installed by default version of the values file (helm-charts/charts/oeml-api/values.yaml)
.
Published metrics:
Metric name | Parameters | Description |
---|---|---|
coinapi_oeml_total_open_order | ExchangeId | Number of all orders placed since the start of oeml |
coinapi_oeml_open_order | ExchangeId | The current number of open orders |
coinapi_oeml_open_order_by_status | ExchangeId, Status | Current number of order statuses |
coinapi_oeml_total_order_per_symbol | ExchangeId, Symbol | Number of orders per symbol since start oeml |
coinapi_oeml_open_position | ExchangeId | The current number of open posiotions |
coinapi_oeml_balance_total | ExchangeId, Symbol | Current balance - total per symbol |
coinapi_oeml_balance_free | ExchangeId, Symbol | Current balance - free per symbol |
coinapi_oeml_balance_locked | ExchangeId, Symbol | Current balance - locked per symbol |
coinapi_oeml_total_error | ExchangeId, ErrorText | Total error by type |
coinapi_oeml_actual_balance_total_usd_by_symbol | ExchangeId, Symbol | Actual total balance usd by symbol |
coinapi_oeml_total_balance_value_in_usd | ExchangeId | Total balance value in dollars |
coinapi_oeml_orders_change_status_time | ExchangeId, Status1, Status2 | Orders change status time (time in miliseconds) |
Deployment
In this section we are listing tools that could be used to deploy or manage our software.
EMS - Managed Cloud REST API
Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.
This section will provide necessary information about the CoinAPI EMS Managed Cloud REST API
protocol.
This API is used to manage the overall deployment of Execution Management System API (EMS API
) software,
which means that in this API, you define the accounts, credentials, and configurations for the order destinations or identify the CoinAPI endpoints where you need to connect to access the EMS API
.
Implemented Standards:
Endpoints
Environment | Url |
---|---|
Production | https://ems-mgmt.coinapi.io/ |
Sandbox | https://ems-mgmt-sandbox.coinapi.io/ |
Authentication
To use resources that require authorized access, you will need to provide an API key to us when making HTTP requests.
There are 2 methods for passing the API key to us, you only need to use one:
- Custom authorization header named
X-CoinAPI-Key
- Query string parameter named
apikey
Custom authorization header
You can authorize by providing additional custom header named X-CoinAPI-Key
and API key as its value.
Assuming that your API key is 73034021-THIS-IS-SAMPLE-KEY
, then the authorization header you should send to us will look like:
X-CoinAPI-Key: 73034021-THIS-IS-SAMPLE-KEY
Query string authorization parameter
You can authorize by providing an additional parameter named apikey
with a value equal to your API key in the query string of your HTTP request.
Assuming that your API key is 73034021-THIS-IS-SAMPLE-KEY
and that you want to request all accounts, then your query string should look like this:
GET /v1/accounts?apikey=73034021-THIS-IS-SAMPLE-KEY
Account
In the account section you can manage the accounts on the exchanges (order destinations).
Get accounts GET
Code samples
curl --request GET \
--url https://ems-mgmt-sandbox.coinapi.io/v1/accounts \
--header 'Accept: application/json' \
--header 'X-CoinAPI-Key: API_KEY'
var client = new RestClient("https://ems-mgmt-sandbox.coinapi.io/v1/accounts");
var request = new RestRequest(Method.GET);
request.AddHeader("Accept", "application/json");
request.AddHeader("X-CoinAPI-Key", "API_KEY");
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-mgmt-sandbox.coinapi.io/v1/accounts"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Accept", "application/json")
req.Header.Add("X-CoinAPI-Key", "API_KEY")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = null;
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://ems-mgmt-sandbox.coinapi.io/v1/accounts");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("X-CoinAPI-Key", "API_KEY");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-mgmt-sandbox.coinapi.io/v1/accounts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"X-CoinAPI-Key: API_KEY"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-mgmt-sandbox.coinapi.io")
headers = {
'Accept': "application/json",
'X-CoinAPI-Key': "API_KEY"
}
conn.request("GET", "/v1/accounts", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-mgmt-sandbox.coinapi.io/v1/accounts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["Accept"] = 'application/json'
request["X-CoinAPI-Key"] = 'API_KEY'
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.get("https://ems-mgmt-sandbox.coinapi.io/v1/accounts")
.header("Accept", "application/json")
.header("X-CoinAPI-Key", "API_KEY")
.asString();
GET /v1/accounts
Get all accounts maintained for your subscription in the EMS API.
Parameters
Parameter | In | Type | Required | Description |
---|---|---|---|---|
filter_exchange_id | query | array[string] | false | Exchange id of the specific account to provide single account instead of the list of all accounts |
Example responses
200 Response
[
{
"exchange_id": "string",
"parameters": [
{
"key": "PublicApiKey",
"value": "36279b02-d24f-40be-a61b-e9fd7de46dd6"
}
]
}
]
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | OK | Inline |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
» exchange_id | string | false | Exchange identifier and optional tag identifying specific account configured when the software will be managing multiple accounts on the same exchange; for eg: BITSTAMP BITSTAMP/7c177641-74bd-4dbe-9b01-2497c12a5f70` BITSTAMP/2574 Allowed separators between the exchange identifier and the tag: ~/.,:;[email protected]#$%^&*-_+=. |
» parameters | [KeyValue] | false | Exchange specific configuration parameters |
»» key | string | false | No description |
»» value | string | false | No description |
Add or update account POST
Code samples
curl --request POST \
--url https://ems-mgmt-sandbox.coinapi.io/v1/accounts \
--header 'Content-Type: application/json' \
--header 'X-CoinAPI-Key: API_KEY' \
--data '{"exchange_id":"string","parameters":[{"key":"PublicApiKey","value":"36279b02-d24f-40be-a61b-e9fd7de46dd6"}]}'
var client = new RestClient("https://ems-mgmt-sandbox.coinapi.io/v1/accounts");
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("X-CoinAPI-Key", "API_KEY");
request.AddParameter("application/json", "{\"exchange_id\":\"string\",\"parameters\":[{\"key\":\"PublicApiKey\",\"value\":\"36279b02-d24f-40be-a61b-e9fd7de46dd6\"}]}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-mgmt-sandbox.coinapi.io/v1/accounts"
payload := strings.NewReader("{\"exchange_id\":\"string\",\"parameters\":[{\"key\":\"PublicApiKey\",\"value\":\"36279b02-d24f-40be-a61b-e9fd7de46dd6\"}]}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("X-CoinAPI-Key", "API_KEY")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = JSON.stringify({
"exchange_id": "string",
"parameters": [
{
"key": "PublicApiKey",
"value": "36279b02-d24f-40be-a61b-e9fd7de46dd6"
}
]
});
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://ems-mgmt-sandbox.coinapi.io/v1/accounts");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-CoinAPI-Key", "API_KEY");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-mgmt-sandbox.coinapi.io/v1/accounts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\"exchange_id\":\"string\",\"parameters\":[{\"key\":\"PublicApiKey\",\"value\":\"36279b02-d24f-40be-a61b-e9fd7de46dd6\"}]}",
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-CoinAPI-Key: API_KEY"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-mgmt-sandbox.coinapi.io")
payload = "{\"exchange_id\":\"string\",\"parameters\":[{\"key\":\"PublicApiKey\",\"value\":\"36279b02-d24f-40be-a61b-e9fd7de46dd6\"}]}"
headers = {
'Content-Type': "application/json",
'X-CoinAPI-Key': "API_KEY"
}
conn.request("POST", "/v1/accounts", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-mgmt-sandbox.coinapi.io/v1/accounts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request["X-CoinAPI-Key"] = 'API_KEY'
request.body = "{\"exchange_id\":\"string\",\"parameters\":[{\"key\":\"PublicApiKey\",\"value\":\"36279b02-d24f-40be-a61b-e9fd7de46dd6\"}]}"
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.post("https://ems-mgmt-sandbox.coinapi.io/v1/accounts")
.header("Content-Type", "application/json")
.header("X-CoinAPI-Key", "API_KEY")
.body("{\"exchange_id\":\"string\",\"parameters\":[{\"key\":\"PublicApiKey\",\"value\":\"36279b02-d24f-40be-a61b-e9fd7de46dd6\"}]}")
.asString();
POST /v1/accounts
Add new or update existing exchange account for your subscription in the EMS API.
Body parameter
{
"exchange_id": "string",
"parameters": [
{
"key": "PublicApiKey",
"value": "36279b02-d24f-40be-a61b-e9fd7de46dd6"
}
]
}
Parameters
Parameter | In | Type | Required | Description |
---|---|---|---|---|
body | body | AccountData | true | Exchange account object that needs to be add/update to the EMS |
» exchange_id | body | string | false | Exchange identifier and optional tag identifying specific account configured when the software will be managing multiple accounts on the same exchange; for eg: |
» parameters | body | [KeyValue] | false | Parameters required to log into the exchange |
»» key | body | string | false | No description |
»» value | body | string | false | No description |
Detailed descriptions
» exchange_id: Exchange identifier and optional tag identifying specific account configured when the software will be managing multiple accounts on the same exchange; for eg:
BITSTAMP
BITSTAMP/7c177641-74bd-4dbe-9b01-2497c12a5f70`
BITSTAMP/2574
Allowed separators between the exchange identifier and the tag: ~/.,:;[email protected]#$%^&*-_+=.
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
400 | Bad Request | Invalid exchange id | None |
405 | Method Not Allowed | Validation exception | None |
Delete account DELETE
Code samples
curl --request DELETE \
--url 'https://ems-mgmt-sandbox.coinapi.io/v1/accounts?exchange_id=string' \
--header 'X-CoinAPI-Key: API_KEY'
var client = new RestClient("https://ems-mgmt-sandbox.coinapi.io/v1/accounts?exchange_id=string");
var request = new RestRequest(Method.DELETE);
request.AddHeader("X-CoinAPI-Key", "API_KEY");
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-mgmt-sandbox.coinapi.io/v1/accounts?exchange_id=string"
req, _ := http.NewRequest("DELETE", url, nil)
req.Header.Add("X-CoinAPI-Key", "API_KEY")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = null;
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("DELETE", "https://ems-mgmt-sandbox.coinapi.io/v1/accounts?exchange_id=string");
xhr.setRequestHeader("X-CoinAPI-Key", "API_KEY");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-mgmt-sandbox.coinapi.io/v1/accounts?exchange_id=string",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_HTTPHEADER => [
"X-CoinAPI-Key: API_KEY"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-mgmt-sandbox.coinapi.io")
headers = { 'X-CoinAPI-Key': "API_KEY" }
conn.request("DELETE", "/v1/accounts?exchange_id=string", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-mgmt-sandbox.coinapi.io/v1/accounts?exchange_id=string")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Delete.new(url)
request["X-CoinAPI-Key"] = 'API_KEY'
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.delete("https://ems-mgmt-sandbox.coinapi.io/v1/accounts?exchange_id=string")
.header("X-CoinAPI-Key", "API_KEY")
.asString();
DELETE /v1/accounts
Delete specific exchange account maintained by the EMS API for your subscription.
Parameters
Parameter | In | Type | Required | Description |
---|---|---|---|---|
exchange_id | query | array[string] | true | Exchange identifier of the account to delete |
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
404 | Not Found | Exchange account not found | None |
Delete all accounts DELETE
Code samples
curl --request DELETE \
--url https://ems-mgmt-sandbox.coinapi.io/v1/accounts/all \
--header 'X-CoinAPI-Key: API_KEY'
var client = new RestClient("https://ems-mgmt-sandbox.coinapi.io/v1/accounts/all");
var request = new RestRequest(Method.DELETE);
request.AddHeader("X-CoinAPI-Key", "API_KEY");
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-mgmt-sandbox.coinapi.io/v1/accounts/all"
req, _ := http.NewRequest("DELETE", url, nil)
req.Header.Add("X-CoinAPI-Key", "API_KEY")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = null;
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("DELETE", "https://ems-mgmt-sandbox.coinapi.io/v1/accounts/all");
xhr.setRequestHeader("X-CoinAPI-Key", "API_KEY");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-mgmt-sandbox.coinapi.io/v1/accounts/all",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_HTTPHEADER => [
"X-CoinAPI-Key: API_KEY"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-mgmt-sandbox.coinapi.io")
headers = { 'X-CoinAPI-Key': "API_KEY" }
conn.request("DELETE", "/v1/accounts/all", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-mgmt-sandbox.coinapi.io/v1/accounts/all")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Delete.new(url)
request["X-CoinAPI-Key"] = 'API_KEY'
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.delete("https://ems-mgmt-sandbox.coinapi.io/v1/accounts/all")
.header("X-CoinAPI-Key", "API_KEY")
.asString();
DELETE /v1/accounts/all
Delete all exchange accounts maintained by the EMS API for your subscription.
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | OK | None |
Exchange
In the exchange section we provide information about the exchanges supported in the EMS API.
Get exchange configuration GET
Code samples
curl --request GET \
--url https://ems-mgmt-sandbox.coinapi.io/v1/exchanges \
--header 'Accept: application/json' \
--header 'X-CoinAPI-Key: API_KEY'
var client = new RestClient("https://ems-mgmt-sandbox.coinapi.io/v1/exchanges");
var request = new RestRequest(Method.GET);
request.AddHeader("Accept", "application/json");
request.AddHeader("X-CoinAPI-Key", "API_KEY");
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-mgmt-sandbox.coinapi.io/v1/exchanges"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Accept", "application/json")
req.Header.Add("X-CoinAPI-Key", "API_KEY")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = null;
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://ems-mgmt-sandbox.coinapi.io/v1/exchanges");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("X-CoinAPI-Key", "API_KEY");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-mgmt-sandbox.coinapi.io/v1/exchanges",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"X-CoinAPI-Key: API_KEY"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-mgmt-sandbox.coinapi.io")
headers = {
'Accept': "application/json",
'X-CoinAPI-Key': "API_KEY"
}
conn.request("GET", "/v1/exchanges", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-mgmt-sandbox.coinapi.io/v1/exchanges")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["Accept"] = 'application/json'
request["X-CoinAPI-Key"] = 'API_KEY'
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.get("https://ems-mgmt-sandbox.coinapi.io/v1/exchanges")
.header("Accept", "application/json")
.header("X-CoinAPI-Key", "API_KEY")
.asString();
GET /v1/exchanges
Get information about the required parameters or server site location of the exchanges supported in the EMS API.
Example responses
200 Response
[
{
"exchange_id": "string",
"location_id": "string",
"required_parameters": [
"string"
]
}
]
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | OK | Inline |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
anonymous | [ExchangeLoginRequire] | false | No description |
» exchange_id | string | false | Exchange identifier and optional tag identifying specific account configured when the software will be managing multiple accounts on the same exchange; for eg: BITSTAMP BITSTAMP/7c177641-74bd-4dbe-9b01-2497c12a5f70` BITSTAMP/2574 Allowed separators between the exchange identifier and the tag: ~/.,:;[email protected]#$%^&*-_+=. |
» location_id | string | false | Location identifier |
» required_parameters | [string] | false | Parameters required to log into the exchange |
Location
In the location section we provide information about the server sites used in the EMS API.
Get site locations GET
Code samples
curl --request GET \
--url https://ems-mgmt-sandbox.coinapi.io/v1/locations \
--header 'Accept: application/json' \
--header 'X-CoinAPI-Key: API_KEY'
var client = new RestClient("https://ems-mgmt-sandbox.coinapi.io/v1/locations");
var request = new RestRequest(Method.GET);
request.AddHeader("Accept", "application/json");
request.AddHeader("X-CoinAPI-Key", "API_KEY");
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-mgmt-sandbox.coinapi.io/v1/locations"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Accept", "application/json")
req.Header.Add("X-CoinAPI-Key", "API_KEY")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = null;
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://ems-mgmt-sandbox.coinapi.io/v1/locations");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("X-CoinAPI-Key", "API_KEY");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-mgmt-sandbox.coinapi.io/v1/locations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"X-CoinAPI-Key: API_KEY"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-mgmt-sandbox.coinapi.io")
headers = {
'Accept': "application/json",
'X-CoinAPI-Key': "API_KEY"
}
conn.request("GET", "/v1/locations", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-mgmt-sandbox.coinapi.io/v1/locations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["Accept"] = 'application/json'
request["X-CoinAPI-Key"] = 'API_KEY'
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.get("https://ems-mgmt-sandbox.coinapi.io/v1/locations")
.header("Accept", "application/json")
.header("X-CoinAPI-Key", "API_KEY")
.asString();
GET /v1/locations
This endpoint providing information about the server site locations supported in the EMS API.
Example responses
200 Response
[
{
"location_id": "aws-us-east-1",
"region_name": "us-east-1",
"provider_name": "aws"
}
]
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | OK | Inline |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
anonymous | [Locations] | false | No description |
» location_id | string | false | CoinAPI location identifier |
» region_name | string | false | Identifier of the region by the location provider |
» provider_name | string | false | Identifier of the location provider |
Endpoints
In the endpoint section we provide information about the EMS API endpoints to the server sites used in the EMS API deployment for your API Key.
Get API endpoints GET
Code samples
curl --request GET \
--url https://ems-mgmt-sandbox.coinapi.io/v1/endpoints \
--header 'Accept: application/json' \
--header 'X-CoinAPI-Key: API_KEY'
var client = new RestClient("https://ems-mgmt-sandbox.coinapi.io/v1/endpoints");
var request = new RestRequest(Method.GET);
request.AddHeader("Accept", "application/json");
request.AddHeader("X-CoinAPI-Key", "API_KEY");
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-mgmt-sandbox.coinapi.io/v1/endpoints"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Accept", "application/json")
req.Header.Add("X-CoinAPI-Key", "API_KEY")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = null;
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://ems-mgmt-sandbox.coinapi.io/v1/endpoints");
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("X-CoinAPI-Key", "API_KEY");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-mgmt-sandbox.coinapi.io/v1/endpoints",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"X-CoinAPI-Key: API_KEY"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-mgmt-sandbox.coinapi.io")
headers = {
'Accept': "application/json",
'X-CoinAPI-Key': "API_KEY"
}
conn.request("GET", "/v1/endpoints", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-mgmt-sandbox.coinapi.io/v1/endpoints")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["Accept"] = 'application/json'
request["X-CoinAPI-Key"] = 'API_KEY'
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.get("https://ems-mgmt-sandbox.coinapi.io/v1/endpoints")
.header("Accept", "application/json")
.header("X-CoinAPI-Key", "API_KEY")
.asString();
GET /v1/endpoints
Get all API endpoints that the EMS API expose for your subscription.
Parameters
Parameter | In | Type | Required | Description |
---|---|---|---|---|
filter_exchange_id | query | array[string] | false | Exchange id |
Example responses
200 Response
[
{
"exchange_id": "KRAKEN",
"location_id": "aws-us-east-2",
"endpoint_schema": "https",
"endpoint_host": "1314.51253.51.ec2.eu-west-1.amazonaws.com",
"endpoint_url": "https://1314.51253.51.ec2.eu-west-1.amazonaws.com/"
}
]
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | OK | Inline |
Response Schema
Status Code 200
Name | Type | Required | Description |
---|---|---|---|
anonymous | [AccountEndpoint] | false | No description |
» exchange_id | string | false | Exchange identifier and optional tag identifying specific account configured when the software will be managing multiple accounts on the same exchange; for eg: BITSTAMP BITSTAMP/7c177641-74bd-4dbe-9b01-2497c12a5f70` BITSTAMP/2574 Allowed separators between the exchange identifier and the tag: ~/.,:;[email protected]#$%^&*-_+=. |
» location_id | string | false | Location identifier |
» endpoint_schema | string | false | Endpoint schema |
» endpoint_host | string | false | Endpoint host |
» endpoint_url | string | false | Endpoint URL |
Certificate
In the certificate section we generate TLS certificates that can be used as method of authenticating to the EMS API.
Get authentication certificate GET
Code samples
curl --request GET \
--url https://ems-mgmt-sandbox.coinapi.io/v1/certificate/pem \
--header 'Accept: text/plain' \
--header 'X-CoinAPI-Key: API_KEY'
var client = new RestClient("https://ems-mgmt-sandbox.coinapi.io/v1/certificate/pem");
var request = new RestRequest(Method.GET);
request.AddHeader("Accept", "text/plain");
request.AddHeader("X-CoinAPI-Key", "API_KEY");
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-mgmt-sandbox.coinapi.io/v1/certificate/pem"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Accept", "text/plain")
req.Header.Add("X-CoinAPI-Key", "API_KEY")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = null;
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://ems-mgmt-sandbox.coinapi.io/v1/certificate/pem");
xhr.setRequestHeader("Accept", "text/plain");
xhr.setRequestHeader("X-CoinAPI-Key", "API_KEY");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-mgmt-sandbox.coinapi.io/v1/certificate/pem",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: text/plain",
"X-CoinAPI-Key: API_KEY"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-mgmt-sandbox.coinapi.io")
headers = {
'Accept': "text/plain",
'X-CoinAPI-Key': "API_KEY"
}
conn.request("GET", "/v1/certificate/pem", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-mgmt-sandbox.coinapi.io/v1/certificate/pem")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["Accept"] = 'text/plain'
request["X-CoinAPI-Key"] = 'API_KEY'
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.get("https://ems-mgmt-sandbox.coinapi.io/v1/certificate/pem")
.header("Accept", "text/plain")
.header("X-CoinAPI-Key", "API_KEY")
.asString();
GET /v1/certificate/pem
Providing PEM file with the Private Key, Public Key and the Certificate to authenticate to the EMS API.
Example responses
200 Response
"-----BEGIN PUBLIC KEY-----\nMIIBIjANB.......\n-----END PUBLIC KEY-----\n-----BEGIN PRIVATE KEY-----\nMIIEvwIAA.......\n-----END PRIVATE KEY-----\n-----BEGIN CERTIFICATE-----\nMIIDEjCCA.......\n-----END CERTIFICATE-----\n"
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | OK | string |
Schemas
AccountInfo
{
"exchange_id": "string"
}
Properties
Name | Type | Required | Description |
---|---|---|---|
exchange_id | string | false | Exchange identifier and optional tag identifying specific account configured when the software will be managing multiple accounts on the same exchange; for eg: BITSTAMP BITSTAMP/7c177641-74bd-4dbe-9b01-2497c12a5f70` BITSTAMP/2574 Allowed separators between the exchange identifier and the tag: ~/.,:;[email protected]#$%^&*-_+=. |
AccountData
{
"exchange_id": "string",
"parameters": [
{
"key": "PublicApiKey",
"value": "36279b02-d24f-40be-a61b-e9fd7de46dd6"
}
]
}
Properties
Name | Type | Required | Description |
---|---|---|---|
exchange_id | string | false | Exchange identifier and optional tag identifying specific account configured when the software will be managing multiple accounts on the same exchange; for eg: BITSTAMP BITSTAMP/7c177641-74bd-4dbe-9b01-2497c12a5f70` BITSTAMP/2574 Allowed separators between the exchange identifier and the tag: ~/.,:;[email protected]#$%^&*-_+=. |
parameters | [KeyValue] | false | Parameters required to log into the exchange |
UpdateAccount
{
"exchange_id": "string",
"parameters": [
{
"key": "PublicApiKey",
"value": "36279b02-d24f-40be-a61b-e9fd7de46dd6"
}
]
}
Properties
Name | Type | Required | Description |
---|---|---|---|
exchange_id | string | false | Exchange identifier and optional tag identifying specific account configured when the software will be managing multiple accounts on the same exchange; for eg: BITSTAMP BITSTAMP/7c177641-74bd-4dbe-9b01-2497c12a5f70` BITSTAMP/2574 Allowed separators between the exchange identifier and the tag: ~/.,:;[email protected]#$%^&*-_+=. |
parameters | [KeyValue] | false | Parameters required to log into the exchange |
GetAccount
{
"exchange_id": "string",
"parameters": [
{
"key": "PublicApiKey",
"value": "36279b02-d24f-40be-a61b-e9fd7de46dd6"
}
]
}
Properties
Name | Type | Required | Description |
---|---|---|---|
exchange_id | string | false | Exchange identifier and optional tag identifying specific account configured when the software will be managing multiple accounts on the same exchange; for eg: BITSTAMP BITSTAMP/7c177641-74bd-4dbe-9b01-2497c12a5f70` BITSTAMP/2574 Allowed separators between the exchange identifier and the tag: ~/.,:;[email protected]#$%^&*-_+=. |
parameters | [KeyValue] | false | Exchange specific configuration parameters |
ExchangeLoginRequire
{
"exchange_id": "string",
"location_id": "string",
"required_parameters": [
"string"
]
}
Properties
Name | Type | Required | Description |
---|---|---|---|
exchange_id | string | false | Exchange identifier and optional tag identifying specific account configured when the software will be managing multiple accounts on the same exchange; for eg: BITSTAMP BITSTAMP/7c177641-74bd-4dbe-9b01-2497c12a5f70` BITSTAMP/2574 Allowed separators between the exchange identifier and the tag: ~/.,:;[email protected]#$%^&*-_+=. |
location_id | string | false | Location identifier |
required_parameters | [string] | false | Parameters required to log into the exchange |
Locations
{
"location_id": "aws-us-east-1",
"region_name": "us-east-1",
"provider_name": "aws"
}
Properties
Name | Type | Required | Description |
---|---|---|---|
location_id | string | false | CoinAPI location identifier |
region_name | string | false | Identifier of the region by the location provider |
provider_name | string | false | Identifier of the location provider |
KeyValue
{
"key": "PublicApiKey",
"value": "36279b02-d24f-40be-a61b-e9fd7de46dd6"
}
Properties
Key Value pair used to configure exchange accounts.
Name | Type | Required | Description |
---|---|---|---|
key | string | false | No description |
value | string | false | No description |
AccountEndpoint
{
"exchange_id": "KRAKEN",
"location_id": "aws-us-east-2",
"endpoint_schema": "https",
"endpoint_host": "1314.51253.51.ec2.eu-west-1.amazonaws.com",
"endpoint_url": "https://1314.51253.51.ec2.eu-west-1.amazonaws.com/"
}
Properties
Name | Type | Required | Description |
---|---|---|---|
exchange_id | string | false | Exchange identifier and optional tag identifying specific account configured when the software will be managing multiple accounts on the same exchange; for eg: BITSTAMP BITSTAMP/7c177641-74bd-4dbe-9b01-2497c12a5f70` BITSTAMP/2574 Allowed separators between the exchange identifier and the tag: ~/.,:;[email protected]#$%^&*-_+=. |
location_id | string | false | Location identifier |
endpoint_schema | string | false | Endpoint schema |
endpoint_host | string | false | Endpoint host |
endpoint_url | string | false | Endpoint URL |
EMS - REST API
Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.
This section will provide necessary information about the CoinAPI EMS REST API
protocol.
This API is also available in the Postman application: https://postman.coinapi.io/
Implemented Standards:
Endpoints
Deployment method | Environment | Url |
---|---|---|
Managed Cloud | Production | Use Managed Cloud REST API /v1/locations to get specific endpoints to each server site where your deployments span |
Managed Cloud | Sandbox | https://ems-gateway-aws-eu-central-1-dev.coinapi.io/ |
Self Hosted | Production | IP Address of the ems-gateway container/excecutable in the closest server site to the caller location |
Self Hosted | Sandbox | IP Address of the ems-gateway container/excecutable in the closest server site to the caller location |
Authentication
If the software is deployed as Self-Hosted
then API do not require authentication as inside your infrastructure, your company is responsible for the security and access controls.
If the software is deployed in our Managed Cloud
, there are 2 methods for authenticating with us, you only need to use one:
- Custom authorization header named
X-CoinAPI-Key
with the API Key - Query string parameter named
apikey
with the API Key - TLS Client Certificate from the
Managed Cloud REST API
(/v1/certificate/pem endpoint) while establishing a TLS session with us.
Custom authorization header
You can authorize by providing additional custom header named X-CoinAPI-Key
and API key as its value.
Assuming that your API key is 73034021-THIS-IS-SAMPLE-KEY
, then the authorization header you should send to us will look like:
X-CoinAPI-Key: 73034021-THIS-IS-SAMPLE-KEY
Query string authorization parameter
You can authorize by providing an additional parameter named apikey
with a value equal to your API key in the query string of your HTTP request.
Assuming that your API key is 73034021-THIS-IS-SAMPLE-KEY
and that you want to request all balances, then your query string should look like this:
GET /v1/balances?apikey=73034021-THIS-IS-SAMPLE-KEY
Orders
Order statuses and the lifecycle are documented in the separate section: EMS / Starter Guide / Order Lifecycle
Get open orders GET
Code samples
curl --request GET \
--url https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders \
--header 'Accept: application/json'
var client = new RestClient("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders");
var request = new RestRequest(Method.GET);
request.AddHeader("Accept", "application/json");
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Accept", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = null;
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders");
xhr.setRequestHeader("Accept", "application/json");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-gateway-aws-eu-central-1-dev.coinapi.io")
headers = { 'Accept': "application/json" }
conn.request("GET", "/v1/orders", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["Accept"] = 'application/json'
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.get("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders")
.header("Accept", "application/json")
.asString();
GET /v1/orders
Get last execution reports for open orders across all or single exchange.
Parameters
Parameter | In | Type | Required | Description |
---|---|---|---|---|
exchange_id | query | string | false | Filter the open orders to the specific exchange. |
Example responses
200 Response
[
{
"exchange_id": "KRAKEN",
"client_order_id": "6ab36bc1-344d-432e-ac6d-0bf44ee64c2b",
"symbol_id_exchange": "XBT/USDT",
"symbol_id_coinapi": "KRAKEN_SPOT_BTC_USDT",
"amount_order": 0.045,
"price": 0.0783,
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "GOOD_TILL_CANCEL",
"expire_time": "2020-01-01T10:45:20.1677709Z",
"exec_inst": [
"MAKER_OR_CANCEL"
],
"client_order_id_format_exchange": "f81211e2-27c4-b86a-8143-01088ba9222c",
"exchange_order_id": 3456456754,
"amount_open": 0.22,
"amount_filled": 0,
"avg_px": 0.0783,
"status": "RECEIVED",
"status_history": [
[
[
[
"RECEIVED",
"2020-05-27T11:16:20.1677709Z"
],
[
"REJECTED",
"2020-05-27T11:16:20.1677710Z"
]
]
]
],
"error_message": "{\"result\":\"error\",\"reason\":\"InsufficientFunds\",\"message\":\"Failed to place buy order on symbol 'BTCUSD' for price $7,000.00 and quantity 0.22 BTC due to insufficient funds\"}",
"fills": [
{
"time": "2020-01-01T10:45:20.1677709Z",
"price": 10799.2,
"amount": 0.002
}
]
}
]
490 Response
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | Collection of order execution reports. | OrderExecutionReports |
490 | Not Applicable | Filtered exchange is unreachable. | MessageReject |
Send new order POST
Code samples
curl --request POST \
--url https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{"exchange_id":"KRAKEN","client_order_id":"6ab36bc1-344d-432e-ac6d-0bf44ee64c2b","symbol_id_exchange":"XBT/USDT","symbol_id_coinapi":"KRAKEN_SPOT_BTC_USDT","amount_order":0.045,"price":0.0783,"side":"BUY","order_type":"LIMIT","time_in_force":"GOOD_TILL_CANCEL","expire_time":"2020-01-01T10:45:20.1677709Z","exec_inst":["MAKER_OR_CANCEL"]}'
var client = new RestClient("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders");
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Accept", "application/json");
request.AddParameter("application/json", "{\"exchange_id\":\"KRAKEN\",\"client_order_id\":\"6ab36bc1-344d-432e-ac6d-0bf44ee64c2b\",\"symbol_id_exchange\":\"XBT/USDT\",\"symbol_id_coinapi\":\"KRAKEN_SPOT_BTC_USDT\",\"amount_order\":0.045,\"price\":0.0783,\"side\":\"BUY\",\"order_type\":\"LIMIT\",\"time_in_force\":\"GOOD_TILL_CANCEL\",\"expire_time\":\"2020-01-01T10:45:20.1677709Z\",\"exec_inst\":[\"MAKER_OR_CANCEL\"]}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders"
payload := strings.NewReader("{\"exchange_id\":\"KRAKEN\",\"client_order_id\":\"6ab36bc1-344d-432e-ac6d-0bf44ee64c2b\",\"symbol_id_exchange\":\"XBT/USDT\",\"symbol_id_coinapi\":\"KRAKEN_SPOT_BTC_USDT\",\"amount_order\":0.045,\"price\":0.0783,\"side\":\"BUY\",\"order_type\":\"LIMIT\",\"time_in_force\":\"GOOD_TILL_CANCEL\",\"expire_time\":\"2020-01-01T10:45:20.1677709Z\",\"exec_inst\":[\"MAKER_OR_CANCEL\"]}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Accept", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = JSON.stringify({
"exchange_id": "KRAKEN",
"client_order_id": "6ab36bc1-344d-432e-ac6d-0bf44ee64c2b",
"symbol_id_exchange": "XBT/USDT",
"symbol_id_coinapi": "KRAKEN_SPOT_BTC_USDT",
"amount_order": 0.045,
"price": 0.0783,
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "GOOD_TILL_CANCEL",
"expire_time": "2020-01-01T10:45:20.1677709Z",
"exec_inst": [
"MAKER_OR_CANCEL"
]
});
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\"exchange_id\":\"KRAKEN\",\"client_order_id\":\"6ab36bc1-344d-432e-ac6d-0bf44ee64c2b\",\"symbol_id_exchange\":\"XBT/USDT\",\"symbol_id_coinapi\":\"KRAKEN_SPOT_BTC_USDT\",\"amount_order\":0.045,\"price\":0.0783,\"side\":\"BUY\",\"order_type\":\"LIMIT\",\"time_in_force\":\"GOOD_TILL_CANCEL\",\"expire_time\":\"2020-01-01T10:45:20.1677709Z\",\"exec_inst\":[\"MAKER_OR_CANCEL\"]}",
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-gateway-aws-eu-central-1-dev.coinapi.io")
payload = "{\"exchange_id\":\"KRAKEN\",\"client_order_id\":\"6ab36bc1-344d-432e-ac6d-0bf44ee64c2b\",\"symbol_id_exchange\":\"XBT/USDT\",\"symbol_id_coinapi\":\"KRAKEN_SPOT_BTC_USDT\",\"amount_order\":0.045,\"price\":0.0783,\"side\":\"BUY\",\"order_type\":\"LIMIT\",\"time_in_force\":\"GOOD_TILL_CANCEL\",\"expire_time\":\"2020-01-01T10:45:20.1677709Z\",\"exec_inst\":[\"MAKER_OR_CANCEL\"]}"
headers = {
'Content-Type': "application/json",
'Accept': "application/json"
}
conn.request("POST", "/v1/orders", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request["Accept"] = 'application/json'
request.body = "{\"exchange_id\":\"KRAKEN\",\"client_order_id\":\"6ab36bc1-344d-432e-ac6d-0bf44ee64c2b\",\"symbol_id_exchange\":\"XBT/USDT\",\"symbol_id_coinapi\":\"KRAKEN_SPOT_BTC_USDT\",\"amount_order\":0.045,\"price\":0.0783,\"side\":\"BUY\",\"order_type\":\"LIMIT\",\"time_in_force\":\"GOOD_TILL_CANCEL\",\"expire_time\":\"2020-01-01T10:45:20.1677709Z\",\"exec_inst\":[\"MAKER_OR_CANCEL\"]}"
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.post("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders")
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.body("{\"exchange_id\":\"KRAKEN\",\"client_order_id\":\"6ab36bc1-344d-432e-ac6d-0bf44ee64c2b\",\"symbol_id_exchange\":\"XBT/USDT\",\"symbol_id_coinapi\":\"KRAKEN_SPOT_BTC_USDT\",\"amount_order\":0.045,\"price\":0.0783,\"side\":\"BUY\",\"order_type\":\"LIMIT\",\"time_in_force\":\"GOOD_TILL_CANCEL\",\"expire_time\":\"2020-01-01T10:45:20.1677709Z\",\"exec_inst\":[\"MAKER_OR_CANCEL\"]}")
.asString();
POST /v1/orders
This request creating new order for the specific exchange.
Body parameter
{
"exchange_id": "KRAKEN",
"client_order_id": "6ab36bc1-344d-432e-ac6d-0bf44ee64c2b",
"symbol_id_exchange": "XBT/USDT",
"symbol_id_coinapi": "KRAKEN_SPOT_BTC_USDT",
"amount_order": 0.045,
"price": 0.0783,
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "GOOD_TILL_CANCEL",
"expire_time": "2020-01-01T10:45:20.1677709Z",
"exec_inst": [
"MAKER_OR_CANCEL"
]
}
Parameters
Parameter | In | Type | Required | Description |
---|---|---|---|---|
body | body | OrderNewSingleRequest | true | OrderNewSingleRequest object. |
» exchange_id | body | string | true | Exchange identifier used to identify the routing destination. |
» client_order_id | body | string | true | The unique identifier of the order assigned by the client. |
» symbol_id_exchange | body | string | false | Exchange symbol. One of the properties (symbol_id_exchange , symbol_id_coinapi ) is required to identify the market for the new order. |
» symbol_id_coinapi | body | string | false | CoinAPI symbol. One of the properties (symbol_id_exchange , symbol_id_coinapi ) is required to identify the market for the new order. |
» amount_order | body | number | true | Order quantity. |
» price | body | number | true | Order price. |
» side | body | OrdSide | true | Side of order. |
» order_type | body | OrdType | true | Order types are documented in the separate section: EMS / Starter Guide / Order parameters / Order type |
» time_in_force | body | TimeInForce | true | Order time in force options are documented in the separate section: EMS / Starter Guide / Order parameters / Time in force |
» expire_time | body | date | false | Expiration time. Conditionaly required for orders with time_in_force = GOOD_TILL_TIME_EXCHANGE or GOOD_TILL_TIME_OEML . |
» exec_inst | body | [string] | false | Order execution instructions are documented in the separate section: EMS / Starter Guide / Order parameters / Execution instructions |
Enumerated Values
Parameter | Value |
---|---|
» side | BUY |
» side | SELL |
» order_type | LIMIT |
» time_in_force | GOOD_TILL_CANCEL |
» time_in_force | GOOD_TILL_TIME_EXCHANGE |
» time_in_force | GOOD_TILL_TIME_OMS |
» time_in_force | FILL_OR_KILL |
» time_in_force | IMMEDIATE_OR_CANCEL |
» exec_inst | MAKER_OR_CANCEL |
» exec_inst | AUCTION_ONLY |
» exec_inst | INDICATION_OF_INTEREST |
Example responses
200 Response
{
"exchange_id": "KRAKEN",
"client_order_id": "6ab36bc1-344d-432e-ac6d-0bf44ee64c2b",
"symbol_id_exchange": "XBT/USDT",
"symbol_id_coinapi": "KRAKEN_SPOT_BTC_USDT",
"amount_order": 0.045,
"price": 0.0783,
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "GOOD_TILL_CANCEL",
"expire_time": "2020-01-01T10:45:20.1677709Z",
"exec_inst": [
"MAKER_OR_CANCEL"
],
"client_order_id_format_exchange": "f81211e2-27c4-b86a-8143-01088ba9222c",
"exchange_order_id": 3456456754,
"amount_open": 0.22,
"amount_filled": 0,
"avg_px": 0.0783,
"status": "RECEIVED",
"status_history": [
[
[
[
"RECEIVED",
"2020-05-27T11:16:20.1677709Z"
],
[
"REJECTED",
"2020-05-27T11:16:20.1677710Z"
]
]
]
],
"error_message": "{\"result\":\"error\",\"reason\":\"InsufficientFunds\",\"message\":\"Failed to place buy order on symbol 'BTCUSD' for price $7,000.00 and quantity 0.22 BTC due to insufficient funds\"}",
"fills": [
{
"time": "2020-01-01T10:45:20.1677709Z",
"price": 10799.2,
"amount": 0.002
}
]
}
490 Response
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | Created | OrderExecutionReport |
400 | Bad Request | Input model validation errors. | ValidationError |
490 | Not Applicable | Exchange is unreachable. | MessageReject |
504 | Gateway Time-out | Exchange didn't responded in the defined timeout. | MessageReject |
Get order execution report GET
Code samples
curl --request GET \
--url https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/status/6ab36bc1-344d-432e-ac6d-0bf44ee64c2b \
--header 'Accept: application/json'
var client = new RestClient("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/status/6ab36bc1-344d-432e-ac6d-0bf44ee64c2b");
var request = new RestRequest(Method.GET);
request.AddHeader("Accept", "application/json");
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/status/6ab36bc1-344d-432e-ac6d-0bf44ee64c2b"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Accept", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = null;
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/status/6ab36bc1-344d-432e-ac6d-0bf44ee64c2b");
xhr.setRequestHeader("Accept", "application/json");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/status/6ab36bc1-344d-432e-ac6d-0bf44ee64c2b",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-gateway-aws-eu-central-1-dev.coinapi.io")
headers = { 'Accept': "application/json" }
conn.request("GET", "/v1/orders/status/6ab36bc1-344d-432e-ac6d-0bf44ee64c2b", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/status/6ab36bc1-344d-432e-ac6d-0bf44ee64c2b")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["Accept"] = 'application/json'
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.get("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/status/6ab36bc1-344d-432e-ac6d-0bf44ee64c2b")
.header("Accept", "application/json")
.asString();
GET /v1/orders/status/{client_order_id}
Get the last order execution report for the specified order. The requested order does not need to be active or opened.
Parameters
Parameter | In | Type | Required | Description |
---|---|---|---|---|
client_order_id | path | string | true | The unique identifier of the order assigned by the client. |
Example responses
200 Response
{
"exchange_id": "KRAKEN",
"client_order_id": "6ab36bc1-344d-432e-ac6d-0bf44ee64c2b",
"symbol_id_exchange": "XBT/USDT",
"symbol_id_coinapi": "KRAKEN_SPOT_BTC_USDT",
"amount_order": 0.045,
"price": 0.0783,
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "GOOD_TILL_CANCEL",
"expire_time": "2020-01-01T10:45:20.1677709Z",
"exec_inst": [
"MAKER_OR_CANCEL"
],
"client_order_id_format_exchange": "f81211e2-27c4-b86a-8143-01088ba9222c",
"exchange_order_id": 3456456754,
"amount_open": 0.22,
"amount_filled": 0,
"avg_px": 0.0783,
"status": "RECEIVED",
"status_history": [
[
[
[
"RECEIVED",
"2020-05-27T11:16:20.1677709Z"
],
[
"REJECTED",
"2020-05-27T11:16:20.1677710Z"
]
]
]
],
"error_message": "{\"result\":\"error\",\"reason\":\"InsufficientFunds\",\"message\":\"Failed to place buy order on symbol 'BTCUSD' for price $7,000.00 and quantity 0.22 BTC due to insufficient funds\"}",
"fills": [
{
"time": "2020-01-01T10:45:20.1677709Z",
"price": 10799.2,
"amount": 0.002
}
]
}
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | The last execution report of the requested order. | OrderExecutionReport |
404 | Not Found | The requested order was not found. | MessageReject |
Cancel order request POST
Code samples
curl --request POST \
--url https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/cancel \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{"exchange_id":"KRAKEN","exchange_order_id":3456456754,"client_order_id":"6ab36bc1-344d-432e-ac6d-0bf44ee64c2b"}'
var client = new RestClient("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/cancel");
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Accept", "application/json");
request.AddParameter("application/json", "{\"exchange_id\":\"KRAKEN\",\"exchange_order_id\":3456456754,\"client_order_id\":\"6ab36bc1-344d-432e-ac6d-0bf44ee64c2b\"}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/cancel"
payload := strings.NewReader("{\"exchange_id\":\"KRAKEN\",\"exchange_order_id\":3456456754,\"client_order_id\":\"6ab36bc1-344d-432e-ac6d-0bf44ee64c2b\"}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Accept", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = JSON.stringify({
"exchange_id": "KRAKEN",
"exchange_order_id": 3456456754,
"client_order_id": "6ab36bc1-344d-432e-ac6d-0bf44ee64c2b"
});
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/cancel");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/cancel",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\"exchange_id\":\"KRAKEN\",\"exchange_order_id\":3456456754,\"client_order_id\":\"6ab36bc1-344d-432e-ac6d-0bf44ee64c2b\"}",
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-gateway-aws-eu-central-1-dev.coinapi.io")
payload = "{\"exchange_id\":\"KRAKEN\",\"exchange_order_id\":3456456754,\"client_order_id\":\"6ab36bc1-344d-432e-ac6d-0bf44ee64c2b\"}"
headers = {
'Content-Type': "application/json",
'Accept': "application/json"
}
conn.request("POST", "/v1/orders/cancel", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/cancel")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request["Accept"] = 'application/json'
request.body = "{\"exchange_id\":\"KRAKEN\",\"exchange_order_id\":3456456754,\"client_order_id\":\"6ab36bc1-344d-432e-ac6d-0bf44ee64c2b\"}"
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.post("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/cancel")
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.body("{\"exchange_id\":\"KRAKEN\",\"exchange_order_id\":3456456754,\"client_order_id\":\"6ab36bc1-344d-432e-ac6d-0bf44ee64c2b\"}")
.asString();
POST /v1/orders/cancel
Request cancel for an existing order. The order can be canceled using the client_order_id
or exchange_order_id
.
Body parameter
{
"exchange_id": "KRAKEN",
"exchange_order_id": 3456456754,
"client_order_id": "6ab36bc1-344d-432e-ac6d-0bf44ee64c2b"
}
Parameters
Parameter | In | Type | Required | Description |
---|---|---|---|---|
body | body | OrderCancelSingleRequest | true | OrderCancelSingleRequest object. |
» exchange_id | body | string | true | Exchange identifier used to identify the routing destination. |
» exchange_order_id | body | string | false | Unique identifier of the order assigned by the exchange or executing system. One of the properties (exchange_order_id , client_order_id ) is required to identify the new order. |
» client_order_id | body | string | false | The unique identifier of the order assigned by the client. One of the properties (exchange_order_id , client_order_id ) is required to identify the new order. |
Example responses
200 Response
{
"exchange_id": "KRAKEN",
"client_order_id": "6ab36bc1-344d-432e-ac6d-0bf44ee64c2b",
"symbol_id_exchange": "XBT/USDT",
"symbol_id_coinapi": "KRAKEN_SPOT_BTC_USDT",
"amount_order": 0.045,
"price": 0.0783,
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "GOOD_TILL_CANCEL",
"expire_time": "2020-01-01T10:45:20.1677709Z",
"exec_inst": [
"MAKER_OR_CANCEL"
],
"client_order_id_format_exchange": "f81211e2-27c4-b86a-8143-01088ba9222c",
"exchange_order_id": 3456456754,
"amount_open": 0.22,
"amount_filled": 0,
"avg_px": 0.0783,
"status": "RECEIVED",
"status_history": [
[
[
[
"RECEIVED",
"2020-05-27T11:16:20.1677709Z"
],
[
"REJECTED",
"2020-05-27T11:16:20.1677710Z"
]
]
]
],
"error_message": "{\"result\":\"error\",\"reason\":\"InsufficientFunds\",\"message\":\"Failed to place buy order on symbol 'BTCUSD' for price $7,000.00 and quantity 0.22 BTC due to insufficient funds\"}",
"fills": [
{
"time": "2020-01-01T10:45:20.1677709Z",
"price": 10799.2,
"amount": 0.002
}
]
}
490 Response
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | The last execution report for the order for which cancelation was requested. | OrderExecutionReport |
400 | Bad Request | Input model validation errors. | ValidationError |
490 | Not Applicable | Exchange is unreachable. | MessageReject |
Cancel all orders request POST
Code samples
curl --request POST \
--url https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/cancel/all \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{"exchange_id":"KRAKEN"}'
var client = new RestClient("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/cancel/all");
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Accept", "application/json");
request.AddParameter("application/json", "{\"exchange_id\":\"KRAKEN\"}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/cancel/all"
payload := strings.NewReader("{\"exchange_id\":\"KRAKEN\"}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Accept", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = JSON.stringify({
"exchange_id": "KRAKEN"
});
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("POST", "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/cancel/all");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Accept", "application/json");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/cancel/all",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "{\"exchange_id\":\"KRAKEN\"}",
CURLOPT_HTTPHEADER => [
"Accept: application/json",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-gateway-aws-eu-central-1-dev.coinapi.io")
payload = "{\"exchange_id\":\"KRAKEN\"}"
headers = {
'Content-Type': "application/json",
'Accept': "application/json"
}
conn.request("POST", "/v1/orders/cancel/all", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/cancel/all")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request["Accept"] = 'application/json'
request.body = "{\"exchange_id\":\"KRAKEN\"}"
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.post("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/orders/cancel/all")
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.body("{\"exchange_id\":\"KRAKEN\"}")
.asString();
POST /v1/orders/cancel/all
This request cancels all open orders on single specified exchange.
Body parameter
{
"exchange_id": "KRAKEN"
}
Parameters
Parameter | In | Type | Required | Description |
---|---|---|---|---|
body | body | OrderCancelAllRequest | true | OrderCancelAllRequest object. |
» exchange_id | body | string | true | Identifier of the exchange from which active orders should be canceled. |
Example responses
200 Response
{
"type": "MESSAGE_REJECT",
"reject_reason": "ORDER_ID_NOT_FOUND",
"exchange_id": "BINANCE",
"message": "Order with ID: BINANCE-7d8a-4888 not found",
"rejected_message": "{\"client_order_id\":\"BINANCE-7d8a-4888\",\"exchange_id\":\"BINANCE\",\"type\":\"ORDER_CANCEL_SINGLE_REQUEST\"}"
}
490 Response
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | Result | MessageReject |
400 | Bad Request | Input model validation errors. | ValidationError |
490 | Not Applicable | Exchange is unreachable. | MessageReject |
Balances
Get balances GET
Code samples
curl --request GET \
--url https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/balances \
--header 'Accept: application/json'
var client = new RestClient("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/balances");
var request = new RestRequest(Method.GET);
request.AddHeader("Accept", "application/json");
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/balances"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Accept", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = null;
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/balances");
xhr.setRequestHeader("Accept", "application/json");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/balances",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-gateway-aws-eu-central-1-dev.coinapi.io")
headers = { 'Accept': "application/json" }
conn.request("GET", "/v1/balances", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/balances")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["Accept"] = 'application/json'
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.get("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/balances")
.header("Accept", "application/json")
.asString();
GET /v1/balances
Get current currency balance from all or single exchange.
Parameters
Parameter | In | Type | Required | Description |
---|---|---|---|---|
exchange_id | query | string | false | Filter the balances to the specific exchange. |
Example responses
200 Response
[
{
"exchange_id": "KRAKEN",
"data": [
{
"asset_id_exchange": "XBT",
"asset_id_coinapi": "BTC",
"balance": 0.00134444,
"available": 0.00134444,
"locked": 0,
"last_updated_by": "EXCHANGE",
"rate_usd": 1355.12,
"traded": 0.007
}
]
}
]
490 Response
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | Collection of balances. | Balances |
490 | Not Applicable | Exchange is unreachable. | MessageReject |
Positions
Get open positions GET
Code samples
curl --request GET \
--url https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/positions \
--header 'Accept: application/json'
var client = new RestClient("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/positions");
var request = new RestRequest(Method.GET);
request.AddHeader("Accept", "application/json");
IRestResponse response = client.Execute(request);
package main
import (
"fmt"
"net/http"
"io/ioutil"
)
func main() {
url := "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/positions"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Accept", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := ioutil.ReadAll(res.Body)
fmt.Println(res)
fmt.Println(string(body))
}
const data = null;
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/positions");
xhr.setRequestHeader("Accept", "application/json");
xhr.send(data);
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/positions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Accept: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
import http.client
conn = http.client.HTTPSConnection("ems-gateway-aws-eu-central-1-dev.coinapi.io")
headers = { 'Accept': "application/json" }
conn.request("GET", "/v1/positions", headers=headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/positions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(url)
request["Accept"] = 'application/json'
response = http.request(request)
puts response.read_body
HttpResponse<String> response = Unirest.get("https://ems-gateway-aws-eu-central-1-dev.coinapi.io/v1/positions")
.header("Accept", "application/json")
.asString();
GET /v1/positions
Get current open positions across all or single exchange.
Parameters
Parameter | In | Type | Required | Description |
---|---|---|---|---|
exchange_id | query | string | false | Filter the balances to the specific exchange. |
Example responses
200 Response
[
{
"exchange_id": "KRAKEN",
"data": [
{
"symbol_id_exchange": "XBTUSD",
"symbol_id_coinapi": "BITMEX_PERP_BTC_USD",
"avg_entry_price": 0.00134444,
"quantity": 7,
"side": "BUY",
"unrealized_pnl": 0,
"leverage": 0,
"cross_margin": true,
"liquidation_price": 0.072323,
"raw_data": "Other information provided by the exchange on this position."
}
]
}
]
490 Response
Responses
Status | Meaning | Description | Schema |
---|---|---|---|
200 | OK | Collection of positons. | Positions |
490 | Not Applicable | Exchange is unreachable. | MessageReject |
Schemas
OrderNewSingleRequest
{
"exchange_id": "KRAKEN",
"client_order_id": "6ab36bc1-344d-432e-ac6d-0bf44ee64c2b",
"symbol_id_exchange": "XBT/USDT",
"symbol_id_coinapi": "KRAKEN_SPOT_BTC_USDT",
"amount_order": 0.045,
"price": 0.0783,
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "GOOD_TILL_CANCEL",
"expire_time": "2020-01-01T10:45:20.1677709Z",
"exec_inst": [
"MAKER_OR_CANCEL"
]
}
Properties
The new order message.
Name | Type | Required | Description |
---|---|---|---|
exchange_id | string | true | Exchange identifier used to identify the routing destination. |
client_order_id | string | true | The unique identifier of the order assigned by the client. |
symbol_id_exchange | string | false | Exchange symbol. One of the properties (symbol_id_exchange , symbol_id_coinapi ) is required to identify the market for the new order. |
symbol_id_coinapi | string | false | CoinAPI symbol. One of the properties (symbol_id_exchange , symbol_id_coinapi ) is required to identify the market for the new order. |
amount_order | number | true | Order quantity. |
price | number | true | Order price. |
side | OrdSide | true | Side of order. |
order_type | OrdType | true | Order types are documented in the separate section: EMS / Starter Guide / Order parameters / Order type |
time_in_force | TimeInForce | true | Order time in force options are documented in the separate section: EMS / Starter Guide / Order parameters / Time in force |
expire_time | date | false | Expiration time. Conditionaly required for orders with time_in_force = GOOD_TILL_TIME_EXCHANGE or GOOD_TILL_TIME_OEML . |
exec_inst | ExecInst | false | Order execution instructions are documented in the separate section: EMS / Starter Guide / Order parameters / Execution instructions |
OrderCancelSingleRequest
{
"exchange_id": "KRAKEN",
"exchange_order_id": 3456456754,
"client_order_id": "6ab36bc1-344d-432e-ac6d-0bf44ee64c2b"
}
Properties
Cancel single order request object.
Name | Type | Required | Description |
---|---|---|---|
exchange_id | string | true | Exchange identifier used to identify the routing destination. |
exchange_order_id | string | false | Unique identifier of the order assigned by the exchange or executing system. One of the properties (exchange_order_id , client_order_id ) is required to identify the new order. |
client_order_id | string | false | The unique identifier of the order assigned by the client. One of the properties (exchange_order_id , client_order_id ) is required to identify the new order. |
OrderCancelAllRequest
{
"exchange_id": "KRAKEN"
}
Properties
Cancel all orders request object.
Name | Type | Required | Description |
---|---|---|---|
exchange_id | string | true | Identifier of the exchange from which active orders should be canceled. |
OrderExecutionReports
[
{
"exchange_id": "KRAKEN",
"client_order_id": "6ab36bc1-344d-432e-ac6d-0bf44ee64c2b",
"symbol_id_exchange": "XBT/USDT",
"symbol_id_coinapi": "KRAKEN_SPOT_BTC_USDT",
"amount_order": 0.045,
"price": 0.0783,
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "GOOD_TILL_CANCEL",
"expire_time": "2020-01-01T10:45:20.1677709Z",
"exec_inst": [
"MAKER_OR_CANCEL"
],
"client_order_id_format_exchange": "f81211e2-27c4-b86a-8143-01088ba9222c",
"exchange_order_id": 3456456754,
"amount_open": 0.22,
"amount_filled": 0,
"avg_px": 0.0783,
"status": "RECEIVED",
"status_history": [
[
[
[
"RECEIVED",
"2020-05-27T11:16:20.1677709Z"
],
[
"REJECTED",
"2020-05-27T11:16:20.1677710Z"
]
]
]
],
"error_message": "{\"result\":\"error\",\"reason\":\"InsufficientFunds\",\"message\":\"Failed to place buy order on symbol 'BTCUSD' for price $7,000.00 and quantity 0.22 BTC due to insufficient funds\"}",
"fills": [
{
"time": "2020-01-01T10:45:20.1677709Z",
"price": 10799.2,
"amount": 0.002
}
]
}
]
Properties
Collection of order execution reports for currently opened orders.
Name | Type | Required | Description |
---|---|---|---|
anonymous | [OrderExecutionReport] | false | Collection of order execution reports for currently opened orders. |
OrderExecutionReport
{
"exchange_id": "KRAKEN",
"client_order_id": "6ab36bc1-344d-432e-ac6d-0bf44ee64c2b",
"symbol_id_exchange": "XBT/USDT",
"symbol_id_coinapi": "KRAKEN_SPOT_BTC_USDT",
"amount_order": 0.045,
"price": 0.0783,
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "GOOD_TILL_CANCEL",
"expire_time": "2020-01-01T10:45:20.1677709Z",
"exec_inst": [
"MAKER_OR_CANCEL"
],
"client_order_id_format_exchange": "f81211e2-27c4-b86a-8143-01088ba9222c",
"exchange_order_id": 3456456754,
"amount_open": 0.22,
"amount_filled": 0,
"avg_px": 0.0783,
"status": "RECEIVED",
"status_history": [
[
[
[
"RECEIVED",
"2020-05-27T11:16:20.1677709Z"
],
[
"REJECTED",
"2020-05-27T11:16:20.1677710Z"
]
]
]
],
"error_message": "{\"result\":\"error\",\"reason\":\"InsufficientFunds\",\"message\":\"Failed to place buy order on symbol 'BTCUSD' for price $7,000.00 and quantity 0.22 BTC due to insufficient funds\"}",
"fills": [
{
"time": "2020-01-01T10:45:20.1677709Z",
"price": 10799.2,
"amount": 0.002
}
]
}
Properties
The order execution report object.
allOf
Name | Type | Required | Description |
---|---|---|---|
anonymous | OrderNewSingleRequest | false | The new order message. |
and
Name | Type | Required | Description |
---|---|---|---|
anonymous | object | false | The order execution report message. |
» client_order_id_format_exchange | string | true | The unique identifier of the order assigned by the client converted to the exchange order tag format for the purpose of tracking it. |
» exchange_order_id | string | false | Unique identifier of the order assigned by the exchange or executing system. |
» amount_open | number | true | Quantity open for further execution. amount_open = amount_order - amount_filled |
» amount_filled | number | true | Total quantity filled. |
» avg_px | number | false | Calculated average price of all fills on this order. |
» status | OrdStatus | true | Order statuses and the lifecycle are documented in the separate section: EMS / Starter Guide / Order Lifecycle |
» status_history | [array] | false | Timestamped history of order status changes. |
» error_message | string | false | Error message. |
» fills | [Fills] | false | Relay fill information on working orders. |
None
Balances
[
{
"exchange_id": "KRAKEN",
"data": [
{
"asset_id_exchange": "XBT",
"asset_id_coinapi": "BTC",
"balance": 0.00134444,
"available": 0.00134444,
"locked": 0,
"last_updated_by": "EXCHANGE",
"rate_usd": 1355.12,
"traded": 0.007
}
]
}
]
Properties
Collection of the balances.
Name | Type | Required | Description |
---|---|---|---|
anonymous | [Balance] | false | Collection of the balances. |
Balance
{
"exchange_id": "KRAKEN",
"data": [
{
"asset_id_exchange": "XBT",
"asset_id_coinapi": "BTC",
"balance": 0.00134444,
"available": 0.00134444,
"locked": 0,
"last_updated_by": "EXCHANGE",
"rate_usd": 1355.12,
"traded": 0.007
}
]
}
Properties
Name | Type | Required | Description |
---|---|---|---|
exchange_id | string | false | Exchange identifier used to identify the routing destination. |
data | [object] | false | No description |
» asset_id_exchange | string | false | Exchange currency code. |
» asset_id_coinapi | string | false | CoinAPI currency code. |
» balance | number(double) | false | Value of the current total currency balance on the exchange. |
» available | number(double) | false | Value of the current available currency balance on the exchange that can be used as collateral. |
» locked | number(double) | false | Value of the current locked currency balance by the exchange. |
» last_updated_by | string | false | Source of the last modification. |
» rate_usd | number(double) | false | Current exchange rate to the USD for the single unit of the currency. |
» traded | number(double) | false | Value of the current total traded. |
Enumerated Values
Property | Value |
---|---|
last_updated_by | INITIALIZATION |
last_updated_by | BALANCE_MANAGER |
last_updated_by | EXCHANGE |
Positions
[
{
"exchange_id": "KRAKEN",
"data": [
{
"symbol_id_exchange": "XBTUSD",
"symbol_id_coinapi": "BITMEX_PERP_BTC_USD",
"avg_entry_price": 0.00134444,
"quantity": 7,
"side": "BUY",
"unrealized_pnl": 0,
"leverage": 0,
"cross_margin": true,
"liquidation_price": 0.072323,
"raw_data": "Other information provided by the exchange on this position."
}
]
}
]
Properties
Collection of the positions.
Name | Type | Required | Description |
---|---|---|---|
anonymous | [Position] | false | Collection of the positions. |
Position
{
"exchange_id": "KRAKEN",
"data": [
{
"symbol_id_exchange": "XBTUSD",
"symbol_id_coinapi": "BITMEX_PERP_BTC_USD",
"avg_entry_price": 0.00134444,
"quantity": 7,
"side": "BUY",
"unrealized_pnl": 0,
"leverage": 0,
"cross_margin": true,
"liquidation_price": 0.072323,
"raw_data": "Other information provided by the exchange on this position."
}
]
}
Properties
Name | Type | Required | Description |
---|---|---|---|
exchange_id | string | false | Exchange identifier used to identify the routing destination. |
data | [object] | false | No description |
» symbol_id_exchange | string | false | Exchange symbol. |
» symbol_id_coinapi | string | false | CoinAPI symbol. |
» avg_entry_price | number | false | Calculated average price of all fills on this position. |
» quantity | number | false | The current position quantity. |
» side | OrdSide | false | Side of order. |
» unrealized_pnl | number | false | Unrealised profit or loss (PNL) of this position. |
» leverage | number | false | Leverage for this position reported by the exchange. |
» cross_margin | boolean | false | Is cross margin mode enable for this position? |
» liquidation_price | number | false | Liquidation price. If mark price will reach this value, the position will be liquidated. |
» raw_data | object | false | No description |
OrdStatus
"RECEIVED"
Properties
Order statuses and the lifecycle are documented in the separate section: EMS / Starter Guide / Order Lifecycle
OrdSide
"BUY"
Properties
Side of order.
OrdType
"LIMIT"
Properties
Order types are documented in the separate section: EMS / Starter Guide / Order parameters / Order type
TimeInForce
"GOOD_TILL_CANCEL"
Properties
Order time in force options are documented in the separate section: EMS / Starter Guide / Order parameters / Time in force
ExecInst
[
"MAKER_OR_CANCEL"
]
Properties
Order execution instructions are documented in the separate section: EMS / Starter Guide / Order parameters / Execution instructions
None
ValidationError
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "d200e8b5-4271a5461ce5342f",
"errors": "string"
}
Properties
JSON validation error.
Name | Type | Required | Description |
---|---|---|---|
type | string | false | No description |
title | string | false | No description |
status | number | false | No description |
traceId | string | false | No description |
errors | string | false | No description |
MessageReject
{
"type": "MESSAGE_REJECT",
"reject_reason": "ORDER_ID_NOT_FOUND",
"exchange_id": "BINANCE",
"message": "Order with ID: BINANCE-7d8a-4888 not found",
"rejected_message": "{\"client_order_id\":\"BINANCE-7d8a-4888\",\"exchange_id\":\"BINANCE\",\"type\":\"ORDER_CANCEL_SINGLE_REQUEST\"}"
}
Properties
MessageReject object.
Name | Type | Required | Description |
---|---|---|---|
type | string | false | Message type, constant. |
reject_reason | RejectReason | false | Cause of rejection. |
exchange_id | string | false | If the message related to exchange, then the identifier of the exchange will be provided. |
message | string | false | Message text. |
rejected_message | string | false | Value of rejected request, if available. |
RejectReason
"ORDER_ID_NOT_FOUND"
Properties
Cause of rejection.
Fills
{
"time": "2020-01-01T10:45:20.1677709Z",
"price": 10799.2,
"amount": 0.002
}
Properties
Relay fill information on working orders.
Name | Type | Required | Description |
---|---|---|---|
time | date | false | Execution time. |
price | number | false | Execution price. |
amount | number | false | Executed quantity. |
EMS - WebSocket API
This section will provide necessary information about the CoinAPI EMS WebSocket API
protocol.
WebSocket API provides real-time communication capacity for order management, execution reports, balances and the positions.
Implemented Standards:
Endpoints
Deployment method | Environment | Url |
---|---|---|
Managed Cloud | Production | Use Managed Cloud REST API /v1/locations to get specific endpoints to each server site where your deployments span |
Managed Cloud | Sandbox | https://ems-gateway-aws-eu-central-1-dev.coinapi.io/ |
Self Hosted | Production | IP Address of the ems-gateway container/excecutable in the closest server site to the caller location |
Self Hosted | Sandbox | IP Address of the ems-gateway container/excecutable in the closest server site to the caller location |
Authentication
If the software is deployed as Self-Hosted
then API do not require authentication as inside your infrastructure, your company is responsible for the security and access controls.
If the software is deployed in our Managed Cloud
, there are 2 methods for authenticating with us, you only need to use one:
- Custom authorization header named
X-CoinAPI-Key
with the API Key - Query string parameter named
apikey
with the API Key - TLS Client Certificate from the
Managed Cloud REST API
(/v1/certificate/pem endpoint) while establishing a TLS session with us.
Custom authorization header
You can authorize by providing additional custom header named X-CoinAPI-Key
and API key as its value.
Assuming that your API key is 73034021-THIS-IS-SAMPLE-KEY
, then the authorization header you should send to us will look like:
X-CoinAPI-Key: 73034021-THIS-IS-SAMPLE-KEY
Query string authorization parameter
You can authorize by providing an additional parameter named apikey
with a value equal to your API key in the query string of your HTTP request.
Assuming that your API key is 73034021-THIS-IS-SAMPLE-KEY
and that you want to request all exchange rates from BTC
asset, then your query string should look like this:
GET /v1/exchangerate/BTC?apikey=73034021-THIS-IS-SAMPLE-KEY
Messages
This section will provide necessary documentation for the WebSocket protocol messages.
The message type is identified by the type
property of the JSON object. This document is organized into sections, each per specific message type
.
Message type |
Trigger | Description |
---|---|---|
SERVER_INFO |
On connection open Every 1 second On update |
Heartbeat and server information. |
ORDER_NEW_SINGLE_REQUEST |
On new order | Submit new order. |
ORDER_CANCEL_SINGLE_REQUEST |
On order cancel | Cancel single order. |
ORDER_CANCEL_ALL_REQUEST |
On order cancel | Cancel all orders. |
ORDER_EXEC_REPORT_SNAPSHOT |
On connection open | Snapshot of all order execution reports. |
ORDER_EXEC_REPORT_UPDATE |
On update | Update of the order execution report. |
BALANCE_SNAPSHOT |
On connection open | Snapshot of all balances. |
BALANCE_UPDATE |
On update | Update of the balance. |
POSITION_SNAPSHOT |
On connection open | Snapshot of all positions. |
POSITION_UPDATE |
On update | Update of the position. |
SYMBOLS_SNAPSHOT |
On connection open | Snapshot of markets symbols. |
MESSAGE_REJECT |
On order placing/cancelling rejection. | Text message. |
SERVER_INFO IN
Example of the
SERVER_INFO
message.
{
"type": "SERVER_INFO",
"time": "2020-02-07T12:37:46.6967101Z",
"instance_guid": "16bab28c-8c7c-4af7-815b-923ea8ecbf4a",
"exchange_id": "BINANCEJE",
"server_version": "1.3521",
"server_name": "HDC2-ENC-06-BAY-05",
"dns_name": "HDC2-ENC-06-BAY-05.us-east-1.corpintra.net",
"is_running": true,
"time_server_start": "2020-02-07T10:25:22.3022141Z"
}
This message is used internally to measure the real-time latency of the link and acts as a heartbeat.
Delivery triggers:
On connection open
Every
1 second
On update
Properties
Name | Type | Description |
---|---|---|
type | string | Message type, constant SERVER_INFO . |
time | datetime | Time message sent time to measure the link latency. |
instance_guid | string | The server process randomly generated GUID. It will change on each software restart. |
exchange_id | string | Exchange identifier. |
server_version | string | Server software version. |
server_name | string | Server name. |
dns_name | string | DNS name. |
is_running | boolean | Is the server on the other side running? Update with the false value will be sent before the shutdown. |
time_server_start | datetime | Time of server software start. |
ORDER_NEW_SINGLE_REQUEST OUT
Example of the
ORDER_NEW_SINGLE_REQUEST
message creating order on theKRAKEN
exchange by thesymbol_id_exchange
.
{
"type": "ORDER_NEW_SINGLE_REQUEST",
"exchange_id": "KRAKEN",
"client_order_id": "6ab36bc1-344d-432e-ac6d-0bf44ee64c2b",
"symbol_id_exchange": "XBT/USDT",
"amount_order": 0.045,
"price": 0.0783,
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "GOOD_TILL_CANCEL",
"expire_time": "2020-01-01T10:45:20.1677709Z",
"exec_inst": ["MAKER_OR_CANCEL"]
}
Another example of the
ORDER_NEW_SINGLE_REQUEST
message creating order on the same market by thesymbol_id_coinapi
.
{
"type": "ORDER_NEW_SINGLE_REQUEST",
"exchange_id": "KRAKEN",
"client_order_id": "6ab36bc1-344d-432e-ac6d-0bf44ee64c2b",
"symbol_id_coinapi": "KRAKEN_SPOT_BTC_USDT",
"amount_order": 0.045,
"price": 0.0783,
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "GOOD_TILL_CANCEL",
"expire_time": "2020-01-01T10:45:20.1677709Z",
"exec_inst": ["MAKER_OR_CANCEL"]
}
This message is used to send a new order to the exchange.
Properties
Parameter | Type | Required | Description |
---|---|---|---|
type | string | true | Message type, constant ORDER_NEW_SINGLE_REQUEST . |
exchange_id | string | true | Exchange identifier. |
client_order_id | string | true | The unique identifier of the order assigned by the client. |
symbol_id_exchange | string | false | Exchange symbol. One of the properties (symbol_id_exchange , symbol_id_coinapi ) is required to identify the market for the new order. |
symbol_id_coinapi | string | false | CoinAPI symbol. One of the properties (symbol_id_exchange , symbol_id_coinapi ) is required to identify the market for the new order. |
amount_order | number | true | Order quantity. |
price | number | true | Order price. |
side | string | true | Side of order. Allowed values: BUY or SELL . |
order_type | string | true | Order types are documented in the separate section: EMS / Starter Guide / Order parameters / Order type |
time_in_force | string | true | Order time in force options are documented in the separate section: EMS / Starter Guide / Order parameters / Time in force |
expire_time | date | false | Expiration time. Conditionaly required for orders with time_in_force = GOOD_TILL_TIME_EXCHANGE or GOOD_TILL_TIME_OEML . |
exec_inst | [string] | false | Order execution instructions are documented in the separate section: EMS / Starter Guide / Order parameters / Execution instructions |
ORDER_CANCEL_SINGLE_REQUEST OUT
Example of the
ORDER_CANCEL_SINGLE_REQUEST
message to cancel a single order identified by theexchange_order_id
on theBITSTAMP
exchange.
{
"type": "ORDER_CANCEL_SINGLE_REQUEST",
"exchange_id": "BITSTAMP",
"exchange_order_id": "1234567"
}
Another example of the
ORDER_CANCEL_SINGLE_REQUEST
message to cancel a single order identified by theclient_order_id
on theBITSTAMP
exchange.
{
"type": "ORDER_CANCEL_SINGLE_REQUEST",
"exchange_id": "BITSTAMP",
"client_order_id": "d8574207d9e3b16a4a5511753eeef1751"
}
Request cancel for an existing order. The order can be canceled using the client_order_id
or exchange_order_id
.
Properties
Parameter | Type | Required | Description |
---|---|---|---|
type | string | true | Message type, constant ORDER_CANCEL_SINGLE_REQUEST . |
exchange_id | string | true | Exchange identifier. |
exchange_order_id | string | false | Unique identifier of the order assigned by the exchange or executing system. One of the properties (exchange_order_id , client_order_id ) is required to identify the order. |
client_order_id | string | false | The unique identifier of the order assigned by the client. One of the properties (exchange_order_id , client_order_id ) is required to identify the order. |
ORDER_CANCEL_ALL_REQUEST OUT
Example of the
ORDER_CANCEL_ALL_REQUEST
message to cancel all open orders on theKRAKEN
exchange.
{
"type": "ORDER_CANCEL_ALL_REQUEST",
"exchange_id": "KRAKEN"
}
This request cancels all open orders on a single specified exchange.
Properties
Parameter | Type | Required | Description |
---|---|---|---|
type | string | true | Message type, constant ORDER_CANCEL_ALL_REQUEST . |
exchange_id | body | string | true |
ORDER_EXEC_REPORT_SNAPSHOT IN
Example of the
ORDER_EXEC_REPORT_SNAPSHOT
message delivering all open orders from the KRAKEN exchange.
{
"type": "ORDER_EXEC_REPORT_SNAPSHOT",
"exchange_id": "KRAKEN",
"data":
[
{
"exchange_id": "KRAKEN",
"client_order_id": "KPP-222389382-AQ",
"exchange_order_id": "90832ASASAS89789-1112",
"symbol_id_exchange": "XBT/USDT",
"symbol_id_coinapi": "KRAKEN_SPOT_BTC_USDT",
"amount_order": 0.045,
"amount_filled": 0,
"amount_open": 0.22,
"status": "NEW",
"price": 0.0783,
"avg_px": 0.0783,
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "GOOD_TILL_CANCEL",
"expire_time": "2020-01-01T10:45:20.1677709Z",
"exec_inst": "MAKER_OR_CANCEL"
"status_history": [
[
"RECEIVED",
"2020-05-27T11:16:20.1677709Z"
],
[
"ROUTING",
"2020-05-27T11:16:20.1677710Z"
],
[
"ROUTED",
"2020-05-27T11:16:20.1677800Z"
],
[
"NEW",
"2020-05-27T11:16:20.1677951Z"
]
],
"fills": [
{
"time": "2020-01-01T10:45:20.1677709Z",
"price": 10799.2,
"amount": 0.002
}
]
}
]
}
This message provides all open orders from the single exchange and will be sent separately for all interconnected exchanges.
When this message is received, then the client must discard all open orders from this exchange and apply the snapshot, which later will be modified by the ORDER_EXEC_REPORT_UPDATE
messages.
Delivery triggers:
- On connection open
Properties
Parameter | In | Type | Required | Description |
---|---|---|---|---|
type | string | true | Message type, constant ORDER_EXEC_REPORT_SNAPSHOT . |
|
data | array | object | true | No description |
» exchange_id | body | string | true | Exchange identifier used to identify the routing destination. |
» client_order_id | body | string | true | The unique identifier of the order assigned by the client. |
» client_order_id_format_exchange | body | string | true | The unique identifier of the order assigned by the client converted to the exchange order tag format for the purpose of tracking it. |
» exchange_order_id | body | string | true | Unique identifier of the order assigned by the exchange or executing system. |
» symbol_id_exchange | body | string | false | Exchange symbol. One of the properties (symbol_id_exchange , symbol_id_coinapi ) is required to identify the market for the new order. |
» symbol_id_coinapi | body | string | false | CoinAPI symbol. One of the properties (symbol_id_exchange , symbol_id_coinapi ) is required to identify the market for the new order. |
» amount_order | body | number | true | Order quantity. |
» amount_filled | body | number | true | Total quantity filled. |
» amount_open | body | number | true | Quantity open for further execution. amount_open = amount_order - amount_filled |
» status | body | string | true | Order statuses and the lifecycle are documented in the separate section: EMS / Starter Guide / Order Lifecycle |
» status_history | body | array | true | Timestamped history of order status changes. |
» price | body | number | true | Order price. |
» avg_px | body | number | true | Calculated average price of all fills on this order. |
» side | body | string | true | Side of order. |
» order_type | body | string | true | Order types are documented in the separate section: EMS / Starter Guide / Order parameters / Order type |
» time_in_force | body | string | true | Order time in force options are documented in the separate section: EMS / Starter Guide / Order parameters / Time in force |
» expire_time | body | date | false | Expiration time. Conditionaly required for orders with time_in_force = GOOD_TILL_TIME_EXCHANGE or GOOD_TILL_TIME_OEML . |
» exec_inst | body | [string] | false | Order execution instructions are documented in the separate section: EMS / Starter Guide / Order parameters / Execution instructions |
» error_message | body | number | true | Error message |
» fills | body | array | true | Relay fill information on working orders |
Enumerated Values
Parameter | Value |
---|---|
» side | BUY |
» side | SELL |
» order_type | LIMIT |
» time_in_force | GOOD_TILL_CANCEL |
» time_in_force | GOOD_TILL_TIME_EXCHANGE |
» time_in_force | GOOD_TILL_TIME_OMS |
» time_in_force | FILL_OR_KILL |
» time_in_force | IMMEDIATE_OR_CANCEL |
» exec_inst | MAKER_OR_CANCEL |
» exec_inst | AUCTION_ONLY |
» exec_inst | INDICATION_OF_INTEREST |
ORDER_EXEC_REPORT_UPDATE IN
Example of the
ORDER_EXEC_REPORT_UPDATE
message notifying that an execution report for the order is changed. In this case, one order changed status, and it's filled.
{
"exchange_id": "KRAKEN",
"client_order_id": "KPP-222389382-AQ",
"client_order_id_format_exchange": "f81211e2-27c4-b86a-8143-01088ba9222c",
"exchange_order_id": "90832ASASAS89789-1112",
"symbol_id_exchange": "XBT/USDT",
"symbol_id_coinapi": "KRAKEN_SPOT_BTC_USDT",
"amount_order": 0.045,
"amount_open": 0,
"amount_filled": 0.045,
"status": "FILLED",
"price": 0.0783,
"avg_px": 0.0783,
"side": "BUY",
"order_type": "LIMIT",
"time_in_force": "GOOD_TILL_CANCEL",
"expire_time": "2020-01-01T10:45:20.1677709Z",
"exec_inst": "MAKER_OR_CANCEL"
"status_history": [
[
"RECEIVED",
"2020-05-27T11:16:20.1677709Z"
],
[
"ROUTING",
"2020-05-27T11:16:20.1677710Z"
],
[
"ROUTED",
"2020-05-27T11:16:20.1677800Z"
],
[
"NEW",
"2020-05-27T11:16:20.1677951Z"
],
[
"FILLED",
"2020-05-27T11:16:30.6456457Z"
]
],
"fills": [
{
"time": "2020-01-01T10:45:20.1677709Z",
"price": 10799.2,
"amount": 0.002
}
]
}
This message is sent to notify the client that the order execution report changed.
When this message is received, then the client must update the execution report in the memory to maintain the current state of execution reports for all open orders.
The initial state of the collection is delivered via the snapshot message ORDER_EXEC_REPORT_SNAPSHOT
.
Delivery triggers:
- On execution report update
Properties
Parameter | In | Type | Required | Description |
---|---|---|---|---|
type | string | true | Message type, constant ORDER_EXEC_REPORT_UPDATE . |
|
exchange_id | body | string | true | Exchange identifier used to identify the routing destination. |
client_order_id | body | string | true | The unique identifier of the order assigned by the client. |
client_order_id_format_exchange | body | string | true | The unique identifier of the order assigned by the client converted to the exchange order tag format for the purpose of tracking it. |
exchange_order_id | body | string | true | Unique identifier of the order assigned by the exchange or executing system. |
symbol_id_exchange | body | string | false | Exchange symbol. One of the properties (symbol_id_exchange , symbol_id_coinapi ) is required to identify the market for the new order. |
symbol_id_coinapi | body | string | false | CoinAPI symbol. One of the properties (symbol_id_exchange , symbol_id_coinapi ) is required to identify the market for the new order. |
amount_order | body | number | true | Order quantity. |
amount_filled | body | number | true | Total quantity filled. |
amount_open | body | number | true | Quantity open for further execution. amount_open = amount_order - amount_filled |
status | body | string | true | Order statuses and the lifecycle are documented in the separate section: EMS / Starter Guide / Order Lifecycle |
status_history | body | array | true | Timestamped history of order status changes. |
price | body | number | true | Order price. |
avg_px | body | number | false | Calculated average price of all fills on this order. |
side | body | string | true | Side of order. |
order_type | body | string | true | Order types are documented in the separate section: EMS / Starter Guide / Order parameters / Order type |
time_in_force | body | string | true | Order time in force options are documented in the separate section: EMS / Starter Guide / Order parameters / Time in force |
expire_time | body | date | false | Expiration time. Conditionaly required for orders with time_in_force = GOOD_TILL_TIME_EXCHANGE or GOOD_TILL_TIME_OEML . |
exec_inst | body | [string] | false | Order execution instructions are documented in the separate section: EMS / Starter Guide / Order parameters / Execution instructions |
error_message | body | number | true | Error message |
fills | body | array | true | Relay fill information on working orders |
Enumerated Values
Parameter | Value |
---|---|
» side | BUY |
» side | SELL |
» order_type | LIMIT |
» time_in_force | GOOD_TILL_CANCEL |
» time_in_force | GOOD_TILL_TIME_EXCHANGE |
» time_in_force | GOOD_TILL_TIME_OMS |
» time_in_force | FILL_OR_KILL |
» time_in_force | IMMEDIATE_OR_CANCEL |
» exec_inst | MAKER_OR_CANCEL |
» exec_inst | AUCTION_ONLY |
» exec_inst | INDICATION_OF_INTEREST |
BALANCE_SNAPSHOT IN
Example of the
BALANCE_SNAPSHOT
message from theKRAKEN
exchange.
{
"type": "BALANCE_SNAPSHOT",
"exchange_id": "KRAKEN",
"data": [
{
"asset_id_exchange": "XBT",
"asset_id_coinapi": "BTC",
"balance": 0.00134444,
"available": 0.00134444,
"locked": 0,
"last_updated_by": "EXCHANGE",
"rate_usd": 9544.21
},
{
"asset_id_exchange": "BCH",
"asset_id_coinapi": "BCHABC",
"balance": 1234,
"available": 1000,
"locked": 234,
"last_updated_by": "BALANCE_MANAGER",
"rate_usd": 228.12
}
]
}
This message provides all balances from the single exchange and will be sent separately for all interconnected exchanges.
When this message is received, then the client must discard all balances from this exchange and apply the snapshot, which later will be modified by the BALANCE_UPDATE
messages.
Delivery triggers:
- On connection open
Properties
Name | Type | Required | Description |
---|---|---|---|
type | string | true | Message type, constant BALANCE_SNAPSHOT . |
exchange_id | string | false | Exchange identifier. |
exchange_id | string | false | Exchange identifier. |
data | [object] | false | No description |
» asset_id_exchange | string | false | Exchange currency code. |
» asset_id_coinapi | string | false | CoinAPI currency code. |
» balance | number(float) | false | Value of the current total currency balance on the exchange. |
» available | number(float) | false | Value of the current available currency balance on the exchange that can be used as collateral. |
» locked | number(float) | false | Value of the current locked currency balance by the exchange. |
» last_updated_by | string | false | Source of the last modification. |
» rate_usd | number(float) | false | Current exchange rate to the USD for the single unit of the currency. |
Enumerated Values
Property | Value |
---|---|
last_updated_by | INITIALIZATION |
last_updated_by | BALANCE_MANAGER |
last_updated_by | EXCHANGE |
BALANCE_UPDATE IN
Example of the
BALANCE_UPDATE
message from theKRAKEN
exchange.
{
"type": "BALANCE_UPDATE",
"exchange_id": "KRAKEN",
"asset_id_exchange": "XBT",
"asset_id_coinapi": "BTC",
"balance": 0.00134444,
"available": 0,
"locked": 0.00134444,
"last_updated_by": "EXCHANGE",
"rate_usd": 9544.21
}
This message is sent to notify the client that the balance for the specific exchange currency pair changed.
When this message is received, the client must update the balance in the memory to maintain the current state of balance across all exchanges and currencies.
The initial state of the collection is delivered via the snapshot message BALANCE_SNAPSHOT
.
Delivery triggers:
- On balance update
Properties
Name | Type | Required | Description |
---|---|---|---|
type | string | true | Message type, constant BALANCE_SNAPSHOT . |
exchange_id | string | false | Exchange identifier. |
exchange_id | string | false | Exchange identifier. |
asset_id_exchange | string | false | Exchange currency code. |
asset_id_coinapi | string | false | CoinAPI currency code. |
balance | number(float) | false | Value of the current total currency balance on the exchange. |
available | number(float) | false | Value of the current available currency balance on the exchange that can be used as collateral. |
locked | number(float) | false | Value of the current locked currency balance by the exchange. |
last_updated_by | string | false | Source of the last modification. |
rate_usd | number(float) | false | Current exchange rate to the USD for the single unit of the currency. |
Enumerated Values
Property | Value |
---|---|
last_updated_by | INITIALIZATION |
last_updated_by | BALANCE_MANAGER |
last_updated_by | EXCHANGE |
POSITION_SNAPSHOT IN
Example of the
POSITION_SNAPSHOT
message from theKRAKENFTS
exchange.
{
"type": "POSITION_SNAPSHOT",
"exchange_id": "KRAKENFTS",
"data":
[
{
"symbol_id_exchange": "XBT/USDT",
"symbol_id_coinapi": "KRAKENFTS_PERP_BTC_USDT",
"avg_entry_price": 0.00134444,
"quantity": 0.00134444,
"side": "BUY",
"unrealised_pnl": 0,
"leverage": 0,
"cross_margin": true,
"liquidation_price": 0.072323
}
]
}
This message provides all positions from the single exchange and will be sent separately for all interconnected exchanges.
When this message is received, then the client must discard al positions from this exchange and apply the snapshot, which later will be modified by the POSITION_UPDATE
messages.
Delivery triggers:
- On connection open
Properties
Name | Type | Required | Description |
---|---|---|---|
type | string | true | Message type, constant POSITION_SNAPSHOT . |
exchange_id | string | false | Exchange identifier. |
data | [object] | false | No description |
» symbol_id_exchange | string | false | Exchange symbol. |
» symbol_id_coinapi | string | false | CoinAPI symbol. |
» avg_entry_price | number | false | Calculated average price of all fills on this position. |
» quantity | number | false | The current position quantity. |
» side | string | false | Side of order. |
» unrealized_pnl | number | false | Unrealised profit or loss (PNL) of this position. |
» leverage | number | false | Leverage for this position reported by the exchange. |
» cross_margin | boolean | false | Is cross margin mode enable for this position? |
» liquidation_price | number | false | Liquidation price. If mark price will reach this value, the position will be liquidated. |
POSITION_UPDATE IN
Example of the
POSITION_UPDATE
message from theKRAKENFTS
exchange.
{
"type": "POSITION_UPDATE",
"exchange_id": "KRAKENFTS",
"symbol_id_exchange": "XBT/USDT",
"symbol_id_coinapi": "KRAKENFTS_PERP_BTC_USDT",
"avg_entry_price": 0.00134444,
"quantity": 0.00134444,
"side": "BUY",
"unrealised_pnl": 0,
"leverage": 0,
"cross_margin": true,
"liquidation_price": 0.072323
}
This message is sent to notify the client that the position changed.
When this message is received, then the client must update the position in the memory to maintain the current state of all positions across all symbols and exchanges.
The initial state of the collection is delivered via the snapshot message POSITION_SNPASHOT
.
Delivery triggers:
- On position update
Properties
Name | Type | Required | Description |
---|---|---|---|
type | string | true | Message type, constant POSITION_SNAPSHOT . |
exchange_id | string | false | Exchange identifier. |
symbol_id_exchange | string | false | Exchange symbol. |
symbol_id_coinapi | string | false | CoinAPI symbol. |
avg_entry_price | number | false | Calculated average price of all fills on this position. |
quantity | number | false | The current position quantity. |
side | string | false | Side of order. |
unrealized_pnl | number | false | Unrealised profit or loss (PNL) of this position. |
leverage | number | false | Leverage for this position reported by the exchange. |
cross_margin | boolean | false | Is cross margin mode enable for this position? |
liquidation_price | number | false | Liquidation price. If mark price will reach this value, the position will be liquidated. |
SYMBOLS_SNAPSHOT IN
Example of the
SYMBOLS_SNAPSHOT
message.
{
"type": "SYMBOLS_SNAPSHOT",
"exchange_id": "BITMEX",
"data": [
{
"symbol_id_coinapi": "BITMEX_FTS_ETH_USD_200925",
"symbol_id_exchange": "ETHUSDU20",
"asset_id_base_exchange": "ETH",
"asset_id_quote_exchange": "USD",
"asset_id_base_coinapi": "ETH",
"asset_id_quote_coinapi": "USD",
"price_precision": 0.010000000,
"size_precision": 1.000000000
},
{
"symbol_id_coinapi": "BITMEX_FTS_LTC_BTC_200925",
"symbol_id_exchange": "LTCU20",
"asset_id_base_exchange": "LTC",
"asset_id_quote_exchange": "XBT",
"asset_id_base_coinapi": "LTC",
"asset_id_quote_coinapi": "BTC",
"price_precision": 0.000001000,
"size_precision": 1.000000000
}
]
}
This message provides all market symbols from the single exchange and will be sent separately for all interconnected exchanges.
When this message is received, then the client must discard all market symbols from this exchange and apply the snapshot.
Delivery triggers:
- On connection open
Properties
Name | Type | Required | Description |
---|---|---|---|
type | string | true | Message type, constant SYMBOLS_SNAPSHOT . |
exchange_id | string | false | Exchange identifier. |
data | [object] | false | No description |
» symbol_id_exchange | string | false | Exchange symbol identifier. |
» symbol_id_coinapi | string | false | CoinAPI symbol identifier. |
» asset_id_base_exchange | string | false | Base asset exchange identifier. |
» asset_id_quote_exchange | string | false | Quote asset exchange identifier. |
» asset_id_base_coinapi | string | false | Base asset CoinAPI identifier. |
» asset_id_quote_coinapi | string | false | Quote asset CoinAPI identifier. |
» price_precision | number | false | Price precision for the symbol. |
» size_precision | number | false | Size precision for the symbol. |
MESSAGE_REJECT IN
Example of the
MESSAGE_REJECT
object.
{
"type": "MESSAGE_REJECT",
"reject_reason": "ORDER_ID_NOT_FOUND",
"exchange_id": "BINANCE",
"message": "Order with ID: BINANCE-7d8a-4888 not found",
"rejected_message": "{\"client_order_id\":\"BINANCE-7d8a-4888\",\"exchange_id\":\"BINANCE\",\"type\":\"ORDER_CANCEL_SINGLE_REQUEST\"}"
}
Object is used to communicate rejection of user order request.
Properties
MessageReject object.
Name | Type | Required | Description |
---|---|---|---|
type | string | true | Message type, constant MESSAGE_REJECT . |
reject_reason | string | true | Cause of rejection. Allowed values: OTHER , EXCHANGE_UNREACHABLE , EXCHANGE_RESPONSE_TIMEOUT , ORDER_ID_NOT_FOUND , INVALID_TYPE , METHOD_NOT_SUPPORTED , JSON_ERROR , |
exchange_id | string | false | If the message related to exchange, then the identifier of the exchange will be provided. |
message | string | true | Message text. |
rejected_message | string | false | Value of rejected request, if available |
EMS - FIX API
Financial Information eXchange (FIX) protocol is an electronic communications protocol initiated in 1992 for international real-time exchange of information related to securities transactions and markets.
You can use it for real-time order management and receiving execution reports from us, and it's an alternative to WebSocket protocol.
Implemented Standards:
Endpoints
Default session configuration:
[DEFAULT]
DefaultApplVerID=FIX.5.0
TransportDataDictionary=FIX/FIXT11.xml
AppDataDictionary=FIX/FIX50.xml
ConnectionType=initiator
ReconnectInterval=1
ResetOnLogon=Y
ResetOnLogout=Y
ResetOnDisconnect=Y
SenderCompID=OMS.FIX.CLIENT
SocketConnectPort=3401
SocketConnectHost=127.0.0.1
FIX 4.4
session configuration:
[SESSION]
BeginString=FIX.4.4
StartTime=00:00:00
EndTime=00:00:00
TargetCompID=CoinAPI.OEML.FIX
DataDictionary=FIX/FIX44.xml
HeartBtInt=1
FileStorePath=store
FIX 5.0
/FIXT 1.1
session configuration:
[SESSION]
BeginString=FIXT.1.1
StartTime=00:00:00
EndTime=00:00:00
TargetCompID=CoinAPI.OEML.FIX
DataDictionary=FIX/FIX50.xml
HeartBtInt=1
FileStorePath=store
Deployment | Environment | Hostname | Port | Authentication |
---|---|---|---|---|
Managed Cloud | Production | Use Managed Cloud REST API /v1/locations to get specific endpoints to each server site where your deployments span | 3301 | TLS Client Certificate |
Managed Cloud | Sandbox | ems-gateway-aws-eu-central-1-dev.coinapi.io |
3301 | TLS Client Certificate |
Self Hosted | Production | IP Address of the ems-gateway container/excecutable in the closest server site to the caller location |
3401 | No |
Self Hosted | Sandbox | IP Address of the ems-gateway container/excecutable in the closest server site to the caller location |
3401 | No |
Our sesssion configuration parameters:
Parameter | Value |
---|---|
Hostname | look at the table above |
Port | look at the table above |
Specifications | FIX 4.4: FIX44.xml FIX 5.0: FIX50.xml FIXT 1.1: FIXT11.xml |
Gateway timezone | UTC |
ReconnectInterval | 1 |
ResetOnLogon | Y |
ResetOnLogout | Y |
ResetOnDisconnect | Y |
SenderCompID | OMS.FIX.CLIENT |
TargetCompID | CoinAPI.OEML.FIX |
SocketConnectPort | look at the table above |
StartTime | 00:00:00 |
EndTime | 00:00:00 |
HeartBtInt | 1 |
Authentication
As you can observe in the documentation below in the Logon
FIX Message, do not contain any authentication data. This is by design.
If the software is deployed as Self-Hosted
then API do not require authentication as inside your infrastructure, your company is responsible for the security and access controls.
If the software is deployed in our Managed Cloud
, then we need your client to provide us the certificate from the Managed Cloud REST API
, while establishing a TLS session with us. We are using the that client certificate provided on the TLS layer, to authenticaticate your FIX session.
Messages
This section will provide necessary documentation for the FIX protocol messages.
New Order Single 35=D
FIX Field Name | WebSocket Field Name | Description |
---|---|---|
ClOrdID |
client_order_id |
The unique identifier of the order assigned by the client. |
ClOrdLinkID |
client_order_id |
The same value as for ClOrdID . |
ExDestination |
exchange_id |
Exchange identifier used to identify the routing destination. |
SecurityID |
symbol_coinapi or symbol_exchange |
CoinAPI or Exchange symbol, depends on the value of SecurityIDSource <22> type |
SecurityIDSource |
N/A | Identifies source of the SecurityID <48> value. 8 = EXCHANGE , 101 = COINAPI |
Symbol |
The same value as for SecurityID . |
|
TransactTime |
N/A | Time this order request was initiated/released by the trader, trading system, or intermediary. |
OrdType |
order_type | Order types are documented in the separate section: EMS / Starter Guide / Order parameters / Order type |
Side |
side | Side of order. |
Price |
price | Order price. |
OrderQty |
amount_order | Order quantity. |
TimeInForce |
time_in_force | Order time in force options are documented in the separate section: EMS / Starter Guide / Order parameters / Time in force |
ExpireTime |
expire_time | Expiration time. Conditionaly required if TimeInForce <59> = GTD |
ExecInst |
exec_inst |
Order execution instructions are documented in the separate section: EMS / Starter Guide / Order parameters / Execution instructions |
Order Cancel Request 35=F
FIX Field Name | WebSocket Field Name | Description |
---|---|---|
ClOrdID |
N/A | Unique ID of cancel request as assigned by the client. |
OrigClOrdID |
client_order_id |
The unique identifier of the order assigned by the client. One of the properties (OrigClOrdID , OrderID ) is required to identify the order. |
OrderID |
exchange_order_id |
Unique identifier of the order assigned by the exchange or executing system. One of the properties (OrigClOrdID , OrderID ) is required to identify the order. |
SecurityExchange |
exchange_id |
Exchange identifier used to identify the routing destination. |
TransactTime |
N/A | Time this order request was initiated/released by the trader, trading system, or intermediary. |
Side |
N/A | This value is ignored. |
Symbol |
N/A | This value is ignored. |
Order Mass Cancel Request 35=q
FIX Field Name | WebSocket Field Name | Description |
---|---|---|
ClOrdID |
N/A | Unique ID of Order Mass Cancel Request <q> as assigned by the client. |
MassCancelRequestType |
N/A | 7 = Cancel all orders |
SecurityExchange |
exchange_id |
Exchange identifier used to identify routing destination. |
Execution Report 35=8
FIX Field Name | WebSocket Field Name | Description |
---|---|---|
OrderID |
client_order_id |
Unique identifier of the order as assigned by client. |
SecondaryOrderID |
exchange_order_id |
Unique identifier of the order assigned by the exchange or executing system. |
ExecID |
N/A | Unique identifier of execution message as assigned by sell-side. |
ExecType |
N/A | I = Order Status. Describes the purpose of the execution report. |
OrdStatus |
status |
Order statuses and the lifecycle are documented in the separate section: EMS / Starter Guide / Order Lifecycle |
SecurityID |
symbol_coinapi or symbol_exchange |
CoinAPI or Exchange symbol, depends on the value of SecurityIDSource <22> type |
SecurityIDSource |
N/A | Identifies source of the SecurityID <48> value. 8 = EXCHANGE , 101 = COINAPI |
Symbol |
The same value as for SecurityID . |
|
SecurityExchange |
exchange_id |
Exchange identifier used to identify the routing destination. |
Side |
side |
Side of order. |
OrderQty |
amount_order |
Quantity ordered. |
CumQty |
amount_filled |
Total quantity filled. |
LeavesQty |
amount_open |
Quantity open for further execution. LeavesQty <151> = OrderQty <38> - CumQty <14> . |