NAV Navbar
python shell

Introduction

Welcome to the FPG REST API. This API provides access to:

Real-Time Cryptocurrency Market Data

Order Management and Execution Engine

Help us improve our product! Please don't hesitate to reach out with suggestions, bug reports, or any other questions/comments.

Notes

Any response field with a "falsy" value (e.g. empty string, empty array, null) is simply omitted from the response.

Base URLs

Sandbox API

https://{user_name}-staging.floating.group

Authentication

The FPG API uses an HMAC-based auth scheme to validate the identity of a caller. Your API key and secret will be delivered to you upon registration. In the event that your credentials are lost or compromised, FPG will provide you with a new set of keys.

Creating a request

All requests must be authenticated and include the following headers:

Example Authentication Framework


import json, hmac, hashlib, time, requests
from requests.auth import AuthBase

# Before implementation, set environmental variables API_KEY and API_SECRET

API_KEY =  # from environment variable
API_SECRET =  # from environment variable

class FPGAuth(AuthBase):
    def __init__(self, api_key, secret_key):
        self.api_key = api_key
        self.secret_key = secret_key

    def __call__(self, request):
        timestamp = str(int(time.time()))
        message = timestamp + self.api_key + request.path_url
        signature = hmac.new(
            bytearray(self.secret_key, 'latin-1'),
            bytearray(message, 'latin-1'),
            hashlib.sha256
        ).hexdigest()

        request.headers.update({
            'FPG-ACCESS-SIGN': signature,
            'FPG-ACCESS-TIMESTAMP': timestamp,
            'FPG-ACCESS-KEY': self.api_key,
        })
        return request

auth = FPGAuth(API_KEY, API_SECRET)

# Hit an error trying to fetch a nonexistent order
user_name = # FPG user name
base_url = f'https://{user_name}-staging.floating.group/v1'
r = requests.get(base_url + '/orders/foo', auth=auth)
print(r.status_code)
print(r.json())

Output

404
{'error': {'message': 'Order "orders/foo" does not exist.'}}

Market Data

GetOrderbook

Get one or multiple orderbooks for a given market across multiple exchanges

GET /v1/spot/book/{symbol}

Parameters

Name In Type Required Description
symbol path string true A market symbol, represented as {base}-{quote}. Must represent a valid market for all requested exchanges.
exchanges query array[string] false A list of exchange names.
consolidated query boolean(boolean) false A boolean flag to request an aggregated orderbook response.

Request

import requests

base = 'BTC'
quote = 'USD'
symbol = f'{base}-{quote}'
exchangeA = 'KRAKEN'
exchangeB = 'GEMINI'

r = requests.get(base_url + f'/v1/spot/book/{symbol}?exchanges={exchangeA}&exchanges={exchangeB}', auth=auth)

print(r.json())

Response

{
  "orderbooks": [
    {
      "level": "ORDERBOOK_LEVEL_TWO",
      "exchangeName": "KRAKEN",
      "baseQuote": "BTC-USD",
      "updateType": "ORDERBOOK_UPDATE_TYPE_SNAPSHOT",
      "timestamp": "2019-05-16T22:11:35.397Z",
      "sequenceHigh": "0",
      "sequenceLow": "0",
      "bids": [
        {
          "price": 7902.9,
          "size": 1.894
        }
      ],
      "asks": [
        {
          "price": 7905.6,
          "size": 0.184
        }
      ]
    }
  ]
}

Response

Field Type Description
orderbooks List[Orderbook] List of orderbooks
error Error A human-readable error message

Orders

ListOrder

List orders in reverse chronological order by createdTime

Request

import requests

r = requests.get(base_url + '/v1/orders', auth=auth)

print(r.json())

GET /v1/orders

Response

{
  "orders": [
    {
      "name": "orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a",
      "createdTime": "2019-05-14T19:57:38.123Z",
      "status": "FPGOS_RUNNING",
      "base": "BTC",
      "quote": "USD",
      "algo": "ACTIVE",
      "orderType": "BUY",
      "exchangeNames": [
        "KRAKEN"
      ],
      "expectedStartTime": "2019-05-14T19:57:38.123Z",
      "expectedEndTime": "2019-05-14T19:57:38.123Z",
      "executionStartTime": "2019-05-14T19:57:38.123Z",
      "executionEndTime": "2019-05-14T19:57:38.123Z"
    }
  ]
}

Response

Field Type Description
orders List[Order] List of orders
error Error A human-readable error message

CreateOrder

Submit an order

Body

body = {
  "base": "BTC",
  "quote": "USD",
  "size": 6,
  "price": 5000,
  "algo": "ACTIVE",
  "orderType": "BUY",
  "exchangeNames": [
    "GEMINI", "KRAKEN"
  ]
}

Request

import requests

r = requests.post(base_url + '/v1/orders', json=body, auth=auth)
print(r.json())

POST /v1/orders

Parameters

Name In Type Required Description
order body Order true An order

Response

{
  "order": {
    "name": "orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a",
    "userName": "fizz",
    "createdTime": "2019-05-14T19:57:38.123Z",
    "status": "FPGOS_RUNNING",
    "base": "BTC",
    "quote": "USD",
    "size": 6,
    "price": 5000,
    "algo": "ACTIVE",
    "orderType": "BUY",
    "exchangeNames": [
      "KRAKEN", "GEMINI"
    ],
    "expectedStartTime": "2019-05-14T19:57:38.123Z",
    "expectedEndTime": "2019-05-14T19:57:38.123Z",
    "executionStartTime": "2019-05-14T19:57:38.123Z",
    "executionEndTime": "2019-05-14T19:57:38.123Z"
  },
  "suborders": [
    {
      "name": "orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a/suborders/460ab297-bb33-41e3-ab75-50cdf7971917",
      "createdTime": "2019-05-21T12:05:42.382Z",
      "status": "FPGEOS_SCHEDULED",
      "base": "BTC",
      "quote": "USD",
      "algo": "ACTIVE",
      "orderType": "BUY",
      "exchangeName": "KRAKEN",
      "expectedSize": 6,
      "expectedPrice": 5000,
      "expectedStartTime": "2019-05-21T12:05:42.382Z",
      "expectedEndTime": "2019-05-21T12:05:42.382Z",
      "executionStartTime": "2019-05-21T12:05:42.382Z",
      "executionEndTime": "2019-05-21T12:05:42.382Z",
      "exchangeOrderId": "87654321"
    },
    {
      "name": "orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a/suborders/ae6a5449-ff00-486a-835a-702eee9cba32",
      "createdTime": "2019-05-21T19:57:38.123Z",
      "status": "FPGEOS_SCHEDULED",
      "base": "BTC",
      "quote": "USD",
      "algo": "ACTIVE",
      "orderType": "BUY",
      "exchangeName": "GEMINI",
      "expectedSize": 6,
      "expectedPrice": 5000,
      "expectedStartTime": "2019-05-21T19:57:38.123Z",
      "expectedEndTime": "2019-05-21T19:57:38.123Z",
      "executionStartTime": "2019-05-21T19:57:38.123Z",
      "executionEndTime": "2019-05-21T19:57:38.123Z",
      "exchangeOrderId": "12345678"
    }
  ]
}

Response

Field Type Description
order Order The submitted order
suborders List[SubOrder] List of generated suborders in chronological order by expectedStartTime
error Error A human-readable error message

GetOrder

Get order by resource name

Request

import requests
order_id = 'af0a83a7-4a39-4f80-a607-4b50c3046e5a'
order = f'orders/{order_id}'
r = requests.get(base_url + f'/v1/{order}', auth=auth)
print(r.json())

GET /v1/{order}

Parameters

Name In Type Required Description
order path string true The order name

Detailed descriptions

order: The order resource name, in the format orders/{order} (e.g. order=orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a).

Response

{
  "suborders": [
    {
      "name": "orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a/suborders/ae6a5449-ff00-486a-835a-702eee9cba37",
      "createdTime": "2019-05-14T19:57:38.123Z",
      "status": "FPGEOS_SCHEDULED",
      "base": "BTC",
      "quote": "USD",
      "algo": "ACTIVE",
      "orderType": "BUY",
      "exchangeName": "KRAKEN",
      "expectedSize": 5,
      "expectedPrice": 5000,
      "expectedStartTime": "2019-05-14T19:57:38.123Z",
      "expectedEndTime": "2019-05-14T19:57:38.123Z",
      "executionStartTime": "2019-05-14T19:57:38.123Z",
      "executionEndTime": "2019-05-14T19:57:38.123Z",
      "exchangeOrderId": "12345678"
    }
  ],
  "order": {
    "name": "orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a",
    "userName": "",
    "createdTime": "2019-05-14T19:57:38.123Z",
    "status": "FPGOS_RUNNING",
    "base": "BTC",
    "quote": "USD",
    "size": 5,
    "price": 5000,
    "algo": "ACTIVE",
    "orderType": "BUY",
    "exchangeNames": [
      "KRAKEN", "GEMINI"
    ],
    "expectedStartTime": "2019-05-14T19:57:38.123Z",
    "expectedEndTime": "2019-05-14T19:57:38.123Z",
    "executionStartTime": "2019-05-14T19:57:38.123Z",
    "executionEndTime": "2019-05-14T19:57:38.123Z"
  }
}

Response

Field Type Description
order Order Order
error Error A human-readable error message

ListSuborders

List suborders in chronological order by expectedStartTime

Request

import requests

order_id = 'af0a83a7-4a39-4f80-a607-4b50c3046e5a'
order = f'orders/{order_id}'

r = requests.get(base_url + f'/v1/{order}/suborders', auth=auth)
print(r.json())

GET /v1/{order}/suborders

Parameters

Name In Type Required Description
order path string true The name of the order to get suborders for

Detailed descriptions

order: The name of the order to get suborders for. It must have the format orders/{order}.

Response

{
  "suborders": [
    {
      "name": "orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a/suborders/ae6a5449-ff00-486a-835a-702eee9cba37",
      "createdTime": "2019-05-14T19:57:38.123Z",
      "status": "FPGEOS_SCHEDULED",
      "base": "BTC",
      "quote": "USD",
      "algo": "ACTIVE",
      "orderType": "BUY",
      "exchangeName": "KRAKEN",
      "expectedSize": 5,
      "expectedPrice": 5000,
      "expectedStartTime": "2019-05-14T19:57:38.123Z",
      "expectedEndTime": "2019-05-14T19:57:38.123Z",
      "executionStartTime": "2019-05-14T19:57:38.123Z",
      "executionEndTime": "2019-05-14T19:57:38.123Z",
      "exchangeOrderId": "12345678"
    }
  ]
}

Response

Field Type Description
suborder List[SubOrder] List of suborders
error Error A human-readable error message

GetSubOrder

Get suborder by resource name

Request

import requests

order_id = 'af0a83a7-4a39-4f80-a607-4b50c3046e5a'
suborder_id = 'ae6a5449-ff00-486a-835a-702eee9cba37'
suborder = f'orders/{order_id}/suborders/{suborder_id}'
r = requests.get(base_url + f'/v1/{suborder}', auth=auth)
print(r.json())

GET /v1/{suborder}

Parameters

Name In Type Required Description
suborder path string true The suborder name

Detailed descriptions

suborder: The suborder resource name. It must have the format orders/{order}/suborders/{suborder}.

Response

{
  "name": "orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a/suborders/ae6a5449-ff00-486a-835a-702eee9cba37",
  "createdTime": "2019-05-14T19:57:38.123Z",
  "status": "SCHEDULED",
  "base": "BTC",
  "quote": "USD",
  "algo": "ACTIVE",
  "orderType": "BUY",
  "exchangeName": "KRAKEN",
  "expectedSize": 5,
  "expectedPrice": 5000,
  "expectedStartTime": "2019-05-14T19:57:38.123Z",
  "expectedEndTime": "2019-05-14T19:57:38.123Z",
  "executionStartTime": "2019-05-14T19:57:38.123Z",
  "executionEndTime": "2019-05-14T19:57:38.123Z",
  "exchangeOrderId": "12345678"
}

Response

Field Type Description
suborder Suborder Suborder
error Error A human-readable error message

Types

Order

Properties

Name Type Required Restrictions Description
name string false none Name of the order, in the form "orders/*"
userName string false none Name of user
createdTime string false none Time that the order started on our system
status string false none Status of the order
base string true Exchange dependent Base currency
quote string true Exchange dependent Quote currency
size number(float) true none Requested size of the order
price number(float) false none Price limit of an order
algo string false DMA, ACTIVE Algorithm type
orderType string true BUY, SELL Order type
exchangeNames List[string] true BINANCE, BITFINEX, GDAX, KRAKEN, POLONIEX, BITTREX, BITSTAMP, HITBTC, OKEX, GEMINI Names of exchanges to route orders
expectedStartTime string(date-time) false Must be greater than current time Time expected to start executing
expectedEndTime string(date-time) false Must be greater than current time Time expected to end execution
executionStartTime string(date-time) false Must be greater than current time Actual execution start time
executionEndTime string(date-time) false Must be greater than current time Actual execution end time

SubOrder

{
  "name": "orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a/suborders/ae6a5449-ff00-486a-835a-702eee9cba37",
  "createdTime": "2019-05-14T19:57:38.123Z",
  "status": "FPGEOS_SCHEDULED",
  "base": "BTC",
  "quote": "USD",
  "algo": "ACTIVE",
  "orderType": "BUY",
  "exchangeName": "KRAKEN",
  "expectedStartTime": "2019-05-14T19:57:38.123Z",
  "expectedEndTime": "2019-05-14T19:57:38.123Z",
  "executionStartTime": "2019-05-14T19:57:38.123Z",
  "executionEndTime": "2019-05-14T19:57:38.123Z"
}

Properties

Name Type Required Restrictions Description
name string true none name of the suborder, structed as "orders/{order_id}/suborders/{suborder_id}"
createdTime string(date-time) false none Time that the order was created at
status string false INVALID, SCHEDULED, SUBMITTING, RUNNING, COMPLETE, PENDING_CANCEL, CANCELLED, FAILED Status of the suborder
base string false none Currency used by the parent order
quote string false none Currency used by the parent order
algo string false DMA, ACTIVE The Algorithm used by the parent order
orderType string false BUY, SELL The order type on the exchange
exchangeName string false true The name of the exchange that the suborder is executing on, limited to Order's exchanges
expectedSize number(float) false none The size that the suborder is expected to get
expectedPrice number(float) false none The price that the suborder is expected to get
expectedStartTime string(date-time) false none The expected time that the suborder should start
expectedEndTime string(date-time) false none The expected that the suborder should be finished
executionSize number(float) false none The size that the suborder was executed at
executionPrice number(float) false none The price that the suborder was executed at
executionStartTime string(date-time) false none Time that the suborder started execution
executionEndTime string(date-time) false none Time that the suborder was finished
exchangeOrderId string false none Name of the order on the given exchange
filled number(float) false none The amount that has already been executed

Orderbook

{
  "id": "659482",
  "level": "ORDERBOOK_LEVEL_TWO",
  "exchangeName": "BINANCE",
  "baseQuote": "ETH-BTC",
  "updateType": "ORDERBOOK_LEVEL_TWO",
  "timestamp": "2019-05-16T22:30:33.687Z",
  "sequenceHigh": "0",
  "sequenceLow": "0",
  "bids": [
    {
      "price": 0.033872,
      "size": 0.209
    }
  ],
  "asks": [
    {
      "price": 0.033888,
      "size": 1.456
    }
  ]
}

Properties

Name Type Required Restrictions Description
id string(uint64) false none FPG internal ID
level OrderbookLevel false ORDERBOOK_LEVEL_TWO Orderbook level
exchangeName string false none none
baseQuote string false none none
updateType OrderbookUpdateType false ORDERBOOK_UPDATE_TYPE_SNAPSHOT Orderbook update type
timestamp string(date-time) false none none
sequenceHigh string(uint64) false none none
sequenceLow string(uint64) false none none
bids [OrderbookEntry] false none Bids, descending
asks [OrderbookEntry] false none Asks, ascending

OrderbookEntry

{
  "price": 240.46,
  "size": 1.125,
  "exchange": "GDAX"
}

Properties

Name Type Required Restrictions Description
price number(double) false none none
size number(double) false none none
exchange string false none none

Error

{
  "message": "Order 'orders/bar' does not exist."
}

An error returned from the server. Note that a Status Code field is intentionally omitted because there's already one included in either the gRPC or HTTP response.

Properties

Name Type Required Restrictions Description
message string false none A human-readable error message

Algorithms

FPG's Algorithms allow the users to adjust familiar benchmark algorithms to suit their needs. Alternatively, you can use our DMA system to make the trades yourself.

Algorithms can be split into three different categories: schedule-driven, evaluative, and opportunitistic.

Schedule-driven includes TWAP and VWAP.

Evaluative includes Passive.

Opportunistic includes Active.

TWAP

The algorithm follows the Time-Weighted Average Price benchmark. Trade n coin over t time, starting from start_date and ending at end_date. The forecasted TWAP price is the default if a price parameter is not overriden by the user.

Parameters

Name Type Required Default Description
price number(float) false none Price limit of an order
size number(float) true none Requested size of the order
expectedStartTime string(date-time) false Must be greater than current time Time expected to start executing
expectedEndTime string(date-time) false Must be greater than current time Time expected to end execution
exchangeNames List[string] true BINANCE, BITFINEX, GDAX, KRAKEN, POLONIEX, BITTREX, BITSTAMP, HITBTC, OKEX, GEMINI Names of exchanges to route orders
base string true Exchange dependent Base currency
quote string true Exchange dependent Quote currency
period int No 10 Number of periods that splits an Order

VWAP

The algorithm follows the Volume-Weighted Average Price benchmark. Trade n coin over t time, starting from start_date and ending at end_date with period P. The forecasted VWAP price is the defeault given the period is the default if a price parameter is not overriden by the user.

Parameters

Parameter Type Required Default Description
price number(float) false none Price limit of an order
size number(float) true none Requested size of the order
expectedStartTime string(date-time) false Must be greater than current time Time expected to start executing
expectedEndTime string(date-time) false Must be greater than current time Time expected to end execution
exchangeNames List[string] true BINANCE, BITFINEX, GDAX, KRAKEN, POLONIEX, BITTREX, BITSTAMP, HITBTC, OKEX, GEMINI Names of exchanges to route orders
base string true Exchange dependent Base currency
quote string true Exchange dependent Quote currency
period int No 10 Number of periods that splits an Order

Passive

The algorithm places only limit orders. The Suborders will track the trading pair's forecasted price wihtout incurring taker fees. This is most useful when volatility is not a concern over a long period of time.

Parameters

Parameter Type Required Default Description
price number(float) false none Price limit of an order
size number(float) true none Requested size of the order
expectedStartTime string(date-time) false Must be greater than current time Time expected to start executing
expectedEndTime string(date-time) false Must be greater than current time Time expected to end execution
exchangeNames List[string] true BINANCE, BITFINEX, GDAX, KRAKEN, POLONIEX, BITTREX, BITSTAMP, HITBTC, OKEX, GEMINI Names of exchanges to route orders
base string true Exchange dependent Base currency
quote string true Exchange dependent Quote currency

Active

The algorithm will aggressively trade and will cross the orderbooks to fulfill the order in the fastest time possible. If a price is given, the orders will execute until it hits the target price. If a time is given, the order will increase in aggressiveness as it approaches expiration. A future release will offload the position to an OTC desk if the order reaches a specific price or time.

Parameters

Parameter Type Required Default Description
price number(float) false none Price limit of an order
size number(float) true none Requested size of the order
expectedStartTime string(date-time) false Must be greater than current time Time expected to start executing
expectedEndTime string(date-time) No None Order will increase price linearly by aggression*(size-filled)/(expectedEndTime-expectedStartTime).
exchangeNames List[string] true BINANCE, BITFINEX, GDAX, KRAKEN, POLONIEX, BITTREX, BITSTAMP, HITBTC, OKEX, GEMINI Names of exchanges to route orders
base string true Exchange dependent Base currency
quote string true Exchange dependent Quote currency
otc bool No N/A If the order is incomplete after expectedEndTime, the remainder will be filled by OTC desks

Errors

The FPG API uses the following error codes:

Error Code Meaning
400 Bad Request -- Request is invalid.
401 Unauthorized -- API key is invalid.
403 Forbidden -- The endpoint requested is hidden for administrators only.
404 Not Found -- The specified endpoint could not be found.
429 Too Many Requests -- You're buying too much bitcoin. Take it easy.
500 Internal Server Error -- We had a problem with our server. Try again later.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.