NAV Navbar
Star

Check your mailbox Something went wrong. Please contact support

Navbar
cURL C# Go Node.js PHP Python Ruby Java
OEML API

OEML - Documentation

This section will provide general information about the Order and Execution Management Layer (OEML) product.

Starter Guide

This section will provide necessary information about the CoinAPI OEML software and enumerate a number of features that it provides.

What is OEML API?

Order and Execution Management Layer (OEML) is a self-hosted software that managing orders, executions and exposure in an efficient, fast, cost-effective, and straightforward manner. An OEML allows you to route orders to multiple cryptocurrency exchanges simultaneously using a simple, robust, and unified Application Programming Interface (API).

Architecture and components

An OEMS cluster can be deployed on single server or multiple servers that will span multiple geographical locations, server sites or cloud providers.

OEMS consist of several components listed and ordered by dependency relationship:

  1. Exchange - Order destination, exchange or broker.

  2. CoinAPI OEML Edge - Software that's responsible for communicating with the single specific order destination for which is deployed. This component is exposing the OEML API for diagnostics purposes which functions visibility are limited to this single destination.

  3. CoinAPI OEML API - Software that's responsible for exposing fully functional the OEML API, maintainitng connection with all instances of CoinAPI OEML Edge.

  4. CoinAPI OEML WebUI - Web interface (GUI) to the OEML API interface. (optional)

  5. Customer Application - Customer software using the OEML API exposed by CoinAPI OEML API component.

Service discovery

The CoinAPI OEML API is capable of automaticaly detecting all your instances of CoinAPI OEML Edge service. This service discovery works by the one of the following methods:

  1. Using the CoinAPI OEML Central Cloud, every time you start CoinAPI OEML Edge, it will register automatically in our central cloud infrastructure.

  2. Using the HashiCorp Consul Cluster.

Using the CoinAPI OEML Central Cloud is a default, simple, and straightforward method. Only one disadvantage of using the CoinAPI OEML 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 OEML 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 OEML API is run.

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. OEML 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:

Closest proximity can be achieved using the:

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 OEML 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:

Self-hosted product

Deploy your property applications and trading algorithms in your company collocated data centers or cloud providers.

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

OEML 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 OEML software is designed to support high-availability deployments out of the box. For each order destination, you can deploy multiple CoinAPI OEML Edge and CoinAPI OEML 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 OEML, your organization can manage exposure and positions in real-time across all supported order destinations and build sophisticated risk management controls.

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 OEML, 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

Our software is listed in public docker repository. To run the software on docker, use the following images:

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 OEML 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 oeml-api latest version

$ helm install oeml-api coinapi-charts/oeml-api -f values.yaml

Install oeml-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 OEML 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 OEML 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
      },
      ]
  }
]

Order lifecycle

This section will describe lifecycle of the order in the OEML 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 OEML.
ROUTING ROUTED The order is (on the wire) between the OEML 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 OEML received a new order via the API.
NEW OEML received an unseen new order from the Order destination. The order was relayed to the destination outside the OEML.
PARTIALLY_FILLED OEML received unseen partially filled order from the Order destination. The order was relayed to the destination outside the OEML.
RECEIVED REJECTED OEML rejected the order.
RECEIVED ROUTING OEML delivering the order to the Order destination.
ROUTING ROUTED OEML sent the order to the Order destination.
ROUTED REJECTED OEML received a message from the exchange that the order was rejected.
ROUTED NEW OEML received a message from the exchange that the order is active in the book in its original state.
ROUTED PARTIALLY_FILLED OEML 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 OEML received a message from the exchange that the order was executed aggressively (removed liquidity).
ROUTED CANCELED OEML 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 OEML received a message from the exchange that part of the passive order was filled.
NEW FILLED OEML received a message from the exchange that the passive order is filled.
NEW PENDING_CANCEL OEML received cancel request for the order and successfully relayed it to the Order destination.
NEW CANCELED OEML received a message from the exchange that the passive order was canceled.
PARTIALLY_FILLED FILLED OEML received a message from the exchange that the remaining part of the passive order is filled.
PARTIALLY_FILLED PENDING_CANCEL OEML received cancel request for the remaining part of the passive order and successfully relayed it to the Order destination.
PARTIALLY_FILLED CANCELED OEML received a message from the exchange that the remaining part of the passive order is canceled.
PENDING_CANCEL NEW OEML 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 OEML 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 OEML 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 OEML 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 OEML sofware.

Order type

OEML 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 OEML 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 OEML 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 OEML 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

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 OEML support of specific execution instructions by the Order destination.

Order destination id MOC AO IOI COD NCOD DNI
BINANCE 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

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:

Output time values are formatted using the following patterns:

  1. yyyy-MM-ddTHH:mm:ss.fffffffZ
  2. yyyy-MM-dd

Management Guide

This section will provide the necessary information on how to manage the CoinAPI OEML software.

To run the OEML cluster, you will need to:

  1. (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.

  2. Run the CoinAPI OEML Edge software instance per each managed exchange account.

  3. Run single or multiple instances of the CoinAPI OEML 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 OEML API Server.

  1. (optional) Run the CoinAPI OEML WebUI to have GUI to the cluster.

  2. Done! All the exchange accounts can be managed using the single API.

Installation

CoinAPI OEML can be installed using several approaches:

Our software is compiled for the following architectures:

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 OEML 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

OEML 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:

If you can't use any of the programs above for reasons like:

Then it's worth trying solutions below (ordered from the best to worst options):

  1. ntp (Linux, FreeBSD, NetBSD, OpenBSD, Solaris, macOS, Windows)

  2. openntpd (Linux, FreeBSD, NetBSD, OpenBSD, Solaris, macOS)

If need the sub-millisecond or sub-nanosecond accuracy take a look there:

  1. Meinberg Radio Clocks

  2. White Rabbit

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.

1.9281 (September 16, 2021)

FEATURES:

BUG FIXES:

1.9136 (September 09, 2021)

BUG FIXES:

1.9066 (August 27, 2021)

FEATURES:

1.8931 (August 11, 2021)

FEATURES:

1.8893 (August 06, 2021)

IMPROVEMENTS:

1.8889 (August 06, 2021)

BUG FIXES:

1.8877 (August 05, 2021)

FEATURES:

1.8821 (July 29, 2021)

FEATURES:

1.8797 (July 23, 2021)

IMPROVEMENTS:

1.8787 (July 22, 2021)

BREAKING CHANGES:

IMPROVEMENTS:

1.8781 (July 22, 2021)

FEATURES:

1.8713 (July 14, 2021)

BUG FIXES:

1.8707 (July 13, 2021)

FEATURES:

IMPROVEMENTS:

Configuration Manual

This section will provide the necessary information how to configure the CoinAPI OEML software.

Configuration keys and values

Configuration keys:

Configuration values:

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):

  1. Command-line arguments

  2. 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:

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:

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

Conditionally required parameters

The table below explains the conditionally required parameters by the OEML:ExchangeId value. For example when OEML:ExchangeId == "BITSTAMP" then OEML:Exchanges:BITSTAMP:CustomerId is required.

OEML:ExchangeId Required 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
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
FTXUS OD:PublicApiKey OD:PrivateApiKey OD:Host OD:Port
DERIBIT 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 OEML WebUI will be used. This step is necessary as we need to discover the address of the OEML API component.

"http_config": { "response_headers": { "Access-Control-Allow-Origin": "*" } }

Integrations & Plugins

This section is reserved for Integrations, plugins or other external tools or modules that make it easier to work with OEML 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.

OEML - 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 OEML REST API protocol.
This API is also available in the Postman application: https://postman.coinapi.io/

Implemented Standards:

Orders

Order statuses and the lifecycle are documented in the separate section: OEML / Starter Guide / Order Lifecycle

Get open orders

Code samples

curl --request GET \
  --url https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.io/v1/orders \
  --header 'Accept: application/json'
var client = new RestClient("https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.io/v1/orders");
xhr.setRequestHeader("Accept", "application/json");

xhr.send(data);
<?php

$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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("13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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

Code samples

curl --request POST \
  --url https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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("13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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: OEML / Starter Guide / Order parameters / Order type
» time_in_force body TimeInForce true Order time in force options are documented in the separate section: OEML / 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: OEML / 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

Code samples

curl --request GET \
  --url https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.io/v1/orders/status/6ab36bc1-344d-432e-ac6d-0bf44ee64c2b \
  --header 'Accept: application/json'
var client = new RestClient("https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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("13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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

Code samples

curl --request POST \
  --url https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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("13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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

Code samples

curl --request POST \
  --url https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.io/v1/orders/cancel/all \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{"exchange_id":"KRAKEN"}'
var client = new RestClient("https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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("13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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

Code samples

curl --request GET \
  --url https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.io/v1/balances \
  --header 'Accept: application/json'
var client = new RestClient("https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.io/v1/balances");
xhr.setRequestHeader("Accept", "application/json");

xhr.send(data);
<?php

$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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("13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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

Code samples

curl --request GET \
  --url https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.io/v1/positions \
  --header 'Accept: application/json'
var client = new RestClient("https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.io/v1/positions");
xhr.setRequestHeader("Accept", "application/json");

xhr.send(data);
<?php

$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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("13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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://13d16e9d-d8b1-4ef4-bc4a-ed8156b2b159.mock.pstmn.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: OEML / Starter Guide / Order parameters / Order type
time_in_force TimeInForce true Order time in force options are documented in the separate section: OEML / 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: OEML / 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: OEML / 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: OEML / Starter Guide / Order Lifecycle

OrdSide

"BUY"

Properties

Side of order.

OrdType

"LIMIT"

Properties

Order types are documented in the separate section: OEML / Starter Guide / Order parameters / Order type

TimeInForce

"GOOD_TILL_CANCEL"

Properties

Order time in force options are documented in the separate section: OEML / Starter Guide / Order parameters / Time in force

ExecInst

[
  "MAKER_OR_CANCEL"
]

Properties

Order execution instructions are documented in the separate section: OEML / 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.

OEML - WebSocket API

This section will provide necessary information about the CoinAPI OEML WebSocket API protocol.

General

WebSocket API provides real-time communication capacity for order management, execution reports, balances and the positions.

Implemented Standards:

Endpoint

The OEML API exposes the HTTP port to which connection should be established over the WebSocket protocol.

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:

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 the KRAKEN exchange by the symbol_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 the symbol_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: OEML / Starter Guide / Order parameters / Order type
time_in_force string true Order time in force options are documented in the separate section: OEML / 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: OEML / 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 the exchange_order_id on the BITSTAMP 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 the client_order_id on the BITSTAMP 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 the KRAKEN 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:

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: OEML / 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: OEML / Starter Guide / Order parameters / Order type
» time_in_force body string true Order time in force options are documented in the separate section: OEML / 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: OEML / 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:

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: OEML / 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: OEML / Starter Guide / Order parameters / Order type
time_in_force body string true Order time in force options are documented in the separate section: OEML / 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: OEML / 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 the KRAKEN 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:

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 the KRAKEN 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:

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 the KRAKENFTS 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:

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 the KRAKENFTS 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:

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:

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

OEML - FIX API

General

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:

Endpoint

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

Our sesssion configuration parameters:

Parameter Value
Hostname (The OEML API Address)
Port 3401
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 3401
StartTime 00:00:00
EndTime 00:00:00
HeartBtInt 1

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: OEML / 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: OEML / 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: OEML / 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: OEML / 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>.
Was this section helpful?
StatusPage: