NAV Navbar
Python Node.js Java

Introduction

Welcome to the FPG REST API! Floating Point Group provides a single point of access to cryptocurrency markets with powerful algorithmic tools, providing exchange connectivity, data ingestion, optimal order execution, and liquidity management. This API provides access to:

Real-Time Cryptocurrency Market Data

Order Management and Execution Engine

Account Management

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

Notes

Base URLs

Beta API

https://beta.api.floating.group

Live API

https://api.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

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, 'utf-8'),
            bytearray(message, 'utf-8'),
            hashlib.sha256
        ).hexdigest()

        request.headers.update({
            'FPG-ACCESS-SIGN': signature,
            'FPG-ACCESS-TIMESTAMP': timestamp,
            'FPG-ACCESS-KEY': self.api_key,
        })
        return request
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import org.json.simple.JSONObject;

public class FPGRequest {

    private String apiKey;
    private String apiSecret;
    private String baseUrl;
    private HttpClient client;

    public FPGRequest(String apiKey, String apiSecret, String baseUrl) {
        this.apiKey = apiKey;
        this.apiSecret = apiSecret;
        this.baseUrl = baseUrl;
        client = HttpClient.newHttpClient();
    }

    private String getSignature(String pathUrl) {
        try {
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
            String message = timestamp + apiKey + pathUrl;

            Mac sha256HMAC = Mac.getInstance("HmacSHA256");
            sha256HMAC.init(new SecretKeySpec(apiSecret.getBytes(), "HmacSHA256"));

            byte[] bytes = sha256HMAC.doFinal(message.getBytes());
            StringBuilder signature = new StringBuilder();
            for (byte b: bytes) {
                signature.append(String.format("%02x", b));
            }
            return signature.toString();
        }
        catch (NoSuchAlgorithmException algorithmException) {
            System.out.println("Algorithm needs to be \"HmacSHA256\".");
        }
        catch (InvalidKeyException keyException) {
            System.out.println("Secret key is not provided.");
        }
        return null;
    }

    // The following is how we would do a GET request. DELETE and PATCH requests can we done similarly.
    public HttpResponse<String> doGETRequest(String pathUrl) {
        try {
            HttpRequest request = HttpRequest.newBuilder()
                    .GET()
                    .headers("FPG-ACCESS-SIGN", getSignature(pathUrl),
                            "FPG-ACCESS-TIMESTAMP", String.valueOf(System.currentTimeMillis() / 1000),
                            "FPG-ACCESS-KEY", apiKey)
                    .uri(new URI(baseUrl + pathUrl))
                    .build();
            return client.send(request, HttpResponse.BodyHandlers.ofString());
        }
        catch (URISyntaxException uriException) {
            System.out.println(String.format("The url trying to hit is %s, which is not valid.", baseUrl + pathUrl));
        }
        catch (IOException ioException) {
            System.out.println("I/O Exception.");
        }
        catch (InterruptedException interruptedException) {
            System.out.println("Encountered interrupted exception.");
        }
        return null;
    }

    // The following is how we would do a POST request.
    public HttpResponse<String> doPOSTRequest(String pathUrl, String postBody) {
        try {
            HttpRequest request = HttpRequest.newBuilder()
                    .POST(HttpRequest.BodyPublishers.ofString(postBody))
                    .headers("FPG-ACCESS-SIGN", getSignature(pathUrl),
                            "FPG-ACCESS-TIMESTAMP", String.valueOf(System.currentTimeMillis() / 1000),
                            "FPG-ACCESS-KEY", apiKey)
                    .uri(new URI(baseUrl + pathUrl))
                    .build();
            return client.send(request, HttpResponse.BodyHandlers.ofString());
        }
        catch (URISyntaxException uriException) {
            System.out.println(String.format("The url trying to hit is %s, which is not valid.", baseUrl + pathUrl));
        }
        catch (IOException ioException) {
            System.out.println("I/O Exception.");
        }
        catch (InterruptedException interruptedException) {
            System.out.println("Encountered interrupted exception.");
        }
        return null;
    }
}
const crypto = require('crypto');

const apiKey = 'public key';
const apiSecret = 'private key';

// The following have the information we need for doing most of the requests, such as GET, PATCH, DELETE, etc. 
function option(pathUrl) {
    var timestamp = Date.now().toString();
    var message = timestamp + apiKey + pathUrl;
    var signature = crypto.createHmac('sha256', apiSecret)
        .update(message)
        .digest('hex');
    var header = {
            'FPG-ACCESS-SIGN': signature,
            'FPG-ACCESS-TIMESTAMP': timestamp,
            'FPG-ACCESS-KEY': apiKey,
        };
    const option = {
            baseUrl: 'https://beta.api.floating.group',
            headers: header
        };
    return option;
};

// The following is for doing POST request. 
function postOption(pathUrl, postBody) {
    var timestamp = Date.now().toString();
    var message = timestamp + apiKey + pathUrl;
    var signature = crypto.createHmac('sha256', apiSecret)
        .update(message)
        .digest('hex');
    var header = {
            'FPG-ACCESS-SIGN': signature,
            'FPG-ACCESS-TIMESTAMP': timestamp,
            'FPG-ACCESS-KEY': apiKey,
        };
    const option = {
            baseUrl: 'https://beta.api.floating.group',
            headers: header,
            form: postBody
        };
    return option;
}

Get Non-Existent Order Request

import requests

API_KEY = 'public key'
API_SECRET = 'private key'

auth = FPGAuth(API_KEY, API_SECRET)

# Hit an error trying to fetch a nonexistent order
base_url = f'https://beta.api.floating.group'

r = requests.get(base_url + '/v1/orders/foo', auth=auth)
print(r.status_code)
print(r.json())
public class Main {

    public static final String KEY = "public key";
    public static final String SECRET = "private key";
    public static final String BASE_URL = "https://beta.api.floating.group";

    public static void main(String[] args) {
        FPGRequest request = new FPGRequest(KEY, SECRET, BASE_URL);
        getNonExistentOrderExample(request);
    }

    public static void getNonExistentOrderExample(FPGRequest request) {
        HttpResponse<String> response = request.doGETRequest("/v1/orders/foo");
        System.out.println(response.statusCode());
        System.out.println(response.body());
    }
}
// We use the 'reqeust' library here: https://github.com/request/request to make our http requests.
const request = require('request');

const pathUrl = '/v1/orders/foo';

request.get(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(response.statusCode);
    console.log(body);
});

Response

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

Market Data

GetExchange

Fetches all available currency markets on an exchange

See all symbols available for querying for market data.

Note that for an invalid exchange name, it will return an error stating that no data was found.

Further, not all symbols or exchanges that data is provided for are available for trading.

Get Exchange Request

import requests

exchange_name = 'kraken'

r = requests.get(base_url + f'/v1/exchanges/{exchange_name}', auth=auth)
print(r.json())
public static void getExchangeExample(FPGRequest request) {
    String exchangeName = "kraken";

    HttpResponse<String> response = request.doGETRequest(String.format("/v1/exchanges/%s", exchangeName));
    System.out.println(response.body());
}
const request = require('request');

const exchangeName = "kraken";
const pathUrl = `/v1/exchanges/${exchangeName}`;

request.get(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

GET /exchanges/{exchange}

Response

{"exchange":
  {
    "name": "KRAKEN",
    "symbols": [
      "EUR-GBP",
      "LINK-EUR",
      "ATOM-EUR",
      "ICX-EUR",
      "LSK-USD",
      ...
      "OMG-EUR",
      "EUR-CHF",
      "ZEC-EUR"
    ]
  }
}

Response

Field Type Description
name string name of the exchange
symbols List[string] List of market symbols available to be queried. A market symbol is represented as {base}-{quote}
error Error A human-readable error message

ListExchanges

List all exchanges and markets available for data querying.

GET /exchanges

List Exchanges Request

import requests

r = requests.get(base_url + f'/v1/exchanges', auth=auth)
print(r.json())
public static void listExchangesExample(FPGRequest request) {
    HttpResponse<String> response = request.doGETRequest("/v1/exchanges");
    System.out.println(response.body());
}
const request = require('request');

const pathUrl = '/v1/exchanges';

request.get(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

Response

{"exchanges": [
  {
    "name": "BINANCE",
    "symbols": [
      "VIB-BTC",
      "ERD-BTC",
      "KEY-USDT",
      "DASH-BNB"
    ]
  },
  {
    "name": "COINBASEPRO",
    "symbols": [
      "BAT-USDC",
      "GNT-USDC",
      "KNC-USD"
    ]
  }]
}

Response

Field Type Description
exchanges List[ExchangeMarkets] List of markets available for data coverage
error Error A human-readable error message

GetOrderbook

Get one or multiple order books for a given market across multiple exchanges

GET /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] true A list of exchange names.
consolidated query boolean(boolean) false A boolean flag to request an aggregated order book response.

Get Orderbook Request

import requests

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

r = requests.get(base_url + f'/v1/book/{symbol}?exchanges={exchangeA}&exchanges={exchangeB}', auth=auth)
print(r.json())
public static void getOrderBookExample(FPGRequest request) {
    String base = "BTC";
    String quote = "USD";
    String symbol = String.format("%s-%s", base, quote);
    String exchangeA = "KRAKEN";
    String exchangeB = "GEMINI";

    HttpResponse<String> response = request.doGETRequest(String.format("/v1/book/%s?exchanges=%s&exchanges=%s", symbol, exchangeA, exchangeB));
    System.out.println(response.body());
}
const request = require('request');

const base = "BTC";
const quote = "USD";
const symbol = `${base}-${quote}`;
const exchangeA = "KRAKEN";
const exchangeB = "GEMINI";
const pathUrl = `/v1/book/${symbol}?exchanges=${exchangeA}&exchanges=${exchangeB}`;

request.get(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

Response

{
  "orderbooks": [
    {
      "level": "ORDERBOOK_LEVEL_TWO",
      "exchangeName": "KRAKEN",
      "symbol": "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 order books
error Error A human-readable error message

Private Data

GetBalance

Get balance across multiple exchanges

Balance is split into three catagories: free, used, and total. Total should always equal free + used.

GET /v1/balances

Parameters

Name In Type Required Description
exchanges query array[string] false A list of exchange names. All exchanges with balance returned if not provided

Get Balance Request

import requests

exchangeA = 'COINBASEPRO'
exchangeB = 'GEMINI'

r = requests.get(base_url + f'/v1/balances?exchanges={exchangeA}&exchanges={exchangeB}', auth=auth)
print(r.json())
public static void getBalanceExample(FPGRequest request) {
    String exchangeA = "COINBASEPRO";
    String exchangeB = "GEMINI";

    HttpResponse<String> response = request.doGETRequest(String.format("/v1/balances?exchanges=%s&exchanges=%s", exchangeA, exchangeB));
    System.out.println(response.body());
}
const request = require('request');

const exchangeA = 'COINBASEPRO';
const exchangeB = 'GEMINI';
const pathUrl =  `/v1/balances?exchanges=${exchangeA}&exchanges=${exchangeB}`;

request.get(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

Response

{
  "balance": {
    "coinbasepro": {
      "currencies": {
        "USDC": {
          "free": "1000",
          "total": "1000"
        }, 
        ...
        "USD": {
          "free": "17376.89",
          "total": "17376.89"
        }
      }
    },
    "consolidated": {
      "currencies": {
        "ZEC": {
          "free": "200",
          "total": "200"
        },
        ...
        "USD": {
          "free": "47183.6729",
          "used": "579.3000",
          "total": "47762.9729"
        },
        "USDC": {
          "free": "1000",
          "total": "1000"
        }
      }
    },
    "gemini": {
      "currencies": {
        "USD": {
          "free": "3566450.78",
          "used": "579820.30",
          "total": "4146271.08"
        },
        ...
        "ETH": {
          "free": "200",
          "total": "200"
        }
      }
   }
  }
}

Response

Name In Type Required Description
exchanges query array[string] false A list of exchange names.
Field Type Description
balance map<string,Balance> Balance of all requested exchanges
error Error A human-readable error message

Orders

CreateOrder

Submit an order

Create Order Request

import requests

post_body = {
  'base': 'BTC',
  'quote': 'USD',
  'size': '6',
  'price': '5000',
  'algo': 'ACTIVELIMIT',
  'orderType': 'BUY',
  'exchangeNames': [
    'GEMINI', 'KRAKEN'
  ]
}

r = requests.post(base_url + '/v1/orders', json=post_body, auth=auth)
print(r.json())
public static void createOrderExample(FPGRequest request) {
    Map<String, String> map = new HashMap<>() {
            {
                put("base", "BTC");
                put("quote", "USD");
                put("size", "6");
                put("price", "5000");
                put("algo", "ACTIVELIMIT");
                put("orderType", "BUY");
                put("exchangeNames", "[GEMINI, KRAKEN]");
            }
        };
    JSONObject postBody = new JSONObject(map);

    HttpResponse<String> response = request.doPOSTRequest("/v1/orders", postBody.toString());
    System.out.println(response.body());
}
const request = require('request');

const postBody = {
        "base": "BTC",
        "quote": "USD",
        "size": "6",
        "price": "5000",
        "algo": "ACTIVELIMIT",
        "orderType": "BUY",
        "exchangeNames": ["GEMINI", "KRAKEN"]
    };
const pathUrl = '/v1/orders';

request.post(pathUrl, postOption(pathUrl, postBody), function (error, response, body) {
    console.log(body);
});

POST /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": "ACTIVELIMIT",
    "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": "ACTIVELIMIT",
      "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": "ACTIVELIMIT",
      "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

Get Order Request

import requests

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

r = requests.get(base_url + f'/v1/{order}', auth=auth)
print(r.json())
public static void getOrderExample(FPGRequest request) {
    String order = "orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a";

    HttpResponse<String> response = request.doGETRequest(String.format("/v1/%s", order));
    System.out.println(response.body());
}
const request = require('request');

const order = 'orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a';
const pathUrl = `/v1/${order}`;

request.get(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

GET /{order}

Parameters

Name In Type Required Description
order path string true The order name
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": "ACTIVELIMIT",
      "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": "ACTIVELIMIT",
    "orderType": "BUY",
    "exchangeNames": [
      "KRAKEN", "GEMINI"
    ],
    "execution_average_price": "5000",
    "execution_cost": "10000",
    "execution_fee": "20",
    "execution_size": "2",
    "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

CancelOrder

Cancel order by resource name

Cancel Order Request

import requests

order_id = 'orders/69d6c60d-e658-4577-8bce-40a80541c0f7'
r = requests.patch(base_url + '/v1/orders/{order_id}', auth=auth)
print(r.json())
public static void cancelOrderExample(FPGRequest request) {
    String order = "orders/69d6c60d-e658-4577-8bce-40a80541c0f7";

    HttpResponse<String> response = request.doPATCHRequest(String.format("/v1/orders/%s", order));
    System.out.println(response.body());
}
const request = require('request');

const order_id = 'orders/69d6c60d-e658-4577-8bce-40a80541c0f7';
const pathUrl = `/v1/orders/${order_id}`;

request.patch(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

PATCH /{order}

Parameters

Name In Type Required Description
order path string true The order name
It must have the format orders/{order}

Response

{
  "order": [
    {
      "name": "orders/69d6c60d-e658-4577-8bce-40a80541c0f7",
      "userName": "users/fpg",
      "createdTime": "2019-08-14T03:05:28.688Z",
      "status": "FPGOS_PENDING_CANCEL",
      "base": "LTC",
      "quote": "USD",
      "size": "0.5",
      "price": "40",
      "algo": "DMA",
      "orderType": "BUY",
      "exchangeNames": [
        "BINANCE"
      ],
      "expectedStartTime": "2019-08-14T03:05:28.688Z",
      "expectedEndTime": "2019-08-14T03:05:28.688Z"
    }
  ]
}

ListOrders

List orders in reverse chronological order by createdTime

List Orders Request

import requests

status='FPGOS_RUNNING'

r = requests.get(base_url + f'/v1/orders?status={status}', auth=auth)
print(r.json())
public static void listOrdersExample(FPGRequest request) {
    String status = "FPGOS_RUNNING";

    HttpResponse<String> response = request.doGETRequest(String.format("/v1/orders?status=%s", status));
    System.out.println(response.body());
}
const request = require('request');

const status='FPGOS_RUNNING';
const pathUrl = `/v1/orders?status=${status}`;

request.get(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

GET /v1/orders

Parameters

Name In Type Required Description
status query string false The status of orders to request. Always prepended with "FPGOS_". Can be: "SUBMITTING", "RUNNING", "COMPLETE", "PENDING_CANCEL", "CANCELLED", or "FAILED"

Response

{
  "orders": [
    {
      "name": "orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a",
      "userName": "users/fpg",
      "createdTime": "2019-05-14T19:57:38.123Z",
      "status": "FPGOS_COMPLETE",
      "base": "BTC",
      "quote": "USD",
      "size": "0.0021",
      "price": "9700.00",
      "algo": "DMA",
      "orderType": "BUY",
      "exchangeNames": ["KRAKEN"],
      "executionAveragePrice": "6619.05",
      "executionCost": "13.9",
      "executionSize": "0.0021",
      "executionFee": "20.12",
      "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

GetSubOrder

Get suborder by resource name

Get Suborder Request

import requests

order_id = 'af0a83a7-4a39-4f80-a607-4b50c3046e5a'
suborder_id = 'ae6a5449-ff00-486a-835a-702eee9cba37'
suborder = f'/v1/orders/{order_id}/suborders/{suborder_id}'

r = requests.get(base_url + f'/{suborder}', auth=auth)
print(r.json())
public static void getSubOrderExample(FPGRequest request) {
    String order_id = "af0a83a7-4a39-4f80-a607-4b50c3046e5a";
    String suborder_id = "ae6a5449-ff00-486a-835a-702eee9cba37";
    String suborder = String.format("/v1/orders/%s/suborders/%s", order_id, suborder_id);

    HttpResponse<String> response = request.doGETRequest(String.format("/%s", suborder));
    System.out.println(response.body());
}
const request = require('request');

const order_id = 'af0a83a7-4a39-4f80-a607-4b50c3046e5a';
const suborder_id = 'ae6a5449-ff00-486a-835a-702eee9cba37';
const suborder = `/v1/orders/${order_id}/suborders/${suborder_id}`;
const pathUrl = `/v1/orders/${order_id}/suborders/${suborder_id}`;

request.get(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

GET /{suborder}

Parameters

Name In Type Required Description
suborder path string true The suborder 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": "ACTIVELIMIT",
  "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

ListSuborders

List suborders in chronological order by expectedStartTime

List Suborders 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())
public static void listSubOrdersExample(FPGRequest request) {
    String order_id = "af0a83a7-4a39-4f80-a607-4b50c3046e5a";
    String order = String.format("orders/%s", order_id);

    HttpResponse<String> response = request.doGETRequest(String.format("/v1/%s/suborders", order));
    System.out.println(response.body());
}
const request = require('request');

const order_id = 'af0a83a7-4a39-4f80-a607-4b50c3046e5a';
const order = `orders/${order_id}`;
const pathUrl = `/v1/${order}/suborders`;

request.get(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

GET /{order}/suborders

Parameters

Name In Type Required Description
order path string true 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": "ACTIVELIMIT",
      "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
suborders List[SubOrder] List of suborders
error Error A human-readable error message

Transactions

GetDepositAddress

Get a deposit address

Get Deposit Address Request

import requests

exchange_name = 'GEMINI'
currency = 'BTC'

r = requests.get(base_url + f'/v1/transactions/deposit?exchangeName={exchange_name}&currency={currency}', auth=auth)
print(r.json())
public static void getDepositAddressExample(FPGRequest request) {
    String exchangeName = "GEMINI";
    String currency = "BTC";

    HttpResponse<String> response = request.doGETRequest(String.format("/v1/transactions/deposit?exchangeName=%s&currency=%s", exchangeName, currency));
    System.out.println(response.body());
}
const request = require('request');

const exchange_name = 'GEMINI';
const currency = 'BTC';
const pathUrl = `/v1/transactions/deposit?exchangeName=${exchange_name}&currency=${currency}`;

request.get(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

GET /v1/transactions/deposit

Parameters

Name In Type Required Description
exchangeName query string true Exchange name
currency query string true Currency name

Response

{
  "depositAddress": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
}

Response

Field Type Description
depositAddress string deposit address for a given currency and exchange
error Error A human-readable error message

CreateWithdraw

Create a withdraw request to an exchange

Create Withdraw Request

import requests

post_body = {
  'amount': '1000',
  'exchangeName': 'GEMINI',
  'currency': 'BTC',
  'address': '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa', 
  'tag': '38545495435', 
  'description': 'coinbasepro' 
}

r = requests.post(base_url + f'/v1/transactions/withdraw', json=post_body, auth=auth)
print(r.json())
public static void createWithdrawExample(FPGRequest request) {
  Map<String, String> map = new HashMap<>() {
            {
                put("amount", "1000");
                put("exchangeNames", "GEMINI");
                put("currency", "BTC");
                put("address", "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
                put("tag", "38545495435");
                put("description", 'coinbasepro')
            }
        };
    JSONObject postBody = new JSONObject(map);

    HttpResponse<String> response = request.doPOSTRequest("/v1/transactions/withdraw", postBody.toString());
    System.out.println(response.body());
}
const request = require('request');

const postBody = {
        "amount": "1000",
        "exchangeName": "GEMINI",
        "currency": "BTC",
        "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", 
        "tag": "38545495435", 
        "description": "coinbasepro" 
    };
const pathUrl = '/v1/transactions/withdraw';

request.post(pathUrl, postOption(pathUrl, postBody), function (error, response, body) {
    console.log(body);
});

POST /v1/transactions/withdraw

Parameters

Name In Type Required Description
amount body float true Withdraw amount
exchangeName body string true Exchange name
currency body string true Currency name
address body string true Withdrawal address
tag body string false Withdrawal address tag for currencies which need tag like 'XRP'
description body string false Identifier for the withdrawal address. Currently this is needed only when withdrawing from kraken

Response

{
  "createdTime": "2019-05-21T19:57:38.123Z",
  "id": "a189-b941-8473",
  "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
  "exchangeName": "GEMINI",
  "currency": "BTC",
  "amount": "1000",
  "tag": "38545495435"
}

Response

Field Type Description
createdTime string(datetime) Time that the withdraw was created on our system
id string ID of the withdrawal given by the exchange
address string Deposit address
tag string Withdrawal address tag for currencies which need tag like 'XRP'
exchangeName string The name of the exchange that will be withdrawn from
currency string Currency
amount string(double) Withdrawn amount
error Error A human-readable error message

WhitelistAddress

Create a whitelist address request to whitelist an address

Create WhitelistAddress Request

import requests

post_body =  {
            'exchange': 'coinbasepro',
            'currency': 'ETH',
            'address': '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
            'tag': '34685394543',
            'address_key': 'key'
  }

r = requests.post(base_url + f'/v1/transactions/whitelist', json=post_body, auth=auth)
print(r.json())
public static void whitelistAddressExample(FPGRequest request) {
  Map<String, String> map = new HashMap<>() {
            {
                put("exchange", "GEMINI");
                put("currency", "BTC");
                put("address", "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
                put("tag", "34685394543");
                put("address_key", "test_key")
            }
        };
    JSONObject postBody = new JSONObject(map);

    HttpResponse<String> response = request.doPOSTRequest("/v1/transactions/whitelist", postBody.toString());
    System.out.println(response.body());
}
const request = require('request');

const postBody ={
            'exchange': 'coinbasepro',
            'currency': 'ETH',
            'address': '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa',
            'tag': '34685394543',
            'address_key': 'key'
  };
const pathUrl = '/v1/transactions/whitelist';

request.post(pathUrl, postOption(pathUrl, postBody), function (error, response, body) {
    console.log(body);
});

POST /v1/transactions/whitelist

Parameters

Name In Type Required Description
exchange body string true Exchange name
currency body string true Currency name
address body string true Withdrawal address
tag body string false Withdrawal address tag for currencies which need tag like 'XRP'
address_key body string false Identifier for the withdrawal address. Currently this is needed only when withdrawing from kraken

Response

GetWhitelistedAddresses

Get all whitelisted addresses for the user

GetWhitelistedAddresses Request

import requests

r = requests.get(base_url + f'/v1/transactions/get_whitelisted_addresses', auth=auth)
print(r.json())
public static void getWhitelistedAddressesExample(FPGRequest request) {


    HttpResponse<String> response = request.doGetRequest("/v1/transactions/get_whitelisted_addresses");
    System.out.println(response.body());
}
const request = require('request');

const pathUrl = '/v1/transactions/get_whitelisted_addresses';

request.get(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

GET /v1/transactions/get_whitelisted_addresses

Response

{
    "addresses": [
        {
          "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
          "currency": "BTC",
          "tag": "34685394543", 
          "address_key": "key"
        }
    ]
}

Response

Field Type Description
addresses List[WithdrawAddress] List of withdraw addresses
error Error A human-readable error message

CreateTransfer

Create a transfer request from one user to another user for a given exchange

Create Transfer Request

import requests

post_body = {
  'amount': '5',
  'exchangeName': 'BITSTAMP',
  'currency': 'BTC',
  'user': 'users/21c482ec-d87b-4f5d-9b85-3aa6228f018b'
}

r = requests.post(base_url + f'/v1/transactions/transfer', json=post_body, auth=auth)
print(r.json())
public static void createTransferExample(FPGRequest request) {
  Map<String, String> map = new HashMap<>() {
            {
                put("amount", "5");
                put("exchangeNames", "BITSTAMP");
                put("currency", "BTC");
                put("user", "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b");
            }
        };
    JSONObject postBody = new JSONObject(map);

    HttpResponse<String> response = request.doPOSTRequest("/v1/transactions/transfer", postBody.toString());
    System.out.println(response.body());
}
const request = require('request');

const postBody = {
        "amount": "5",
        "exchangeName": "BITSTAMP",
        "currency": "BTC",
        "user": "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b"
    };
const pathUrl = '/v1/transactions/transfer';

request.post(pathUrl, postOption(pathUrl, postBody), function (error, response, body) {
    console.log(body);
});

POST /v1/transactions/transfer

Parameters

Name In Type Required Description
amount body float true Transfer amount
exchangeName body string true Exchange name
currency body string true Currency name
user body string true Name of a user

Response

{
  "debitorTransaction": {
    "createdTime": "2019-05-21T19:57:38.123Z",
    "id": "internal",
    "address": "internal",
    "exchangeName": "BITSTAMP",
    "currency": "BTC",
    "amount": "5"
  },
  "creditorTransaction": {
    "createdTime": "2019-05-21T19:57:38.123Z",
    "id": "internal",
    "address": "internal",
    "exchangeName": "BITSTAMP",
    "currency": "BTC",
    "amount": "5"
  }
}

Response

Field Type Description
createdTime string(datetime) Time that the transfer was created on our system
id string "internal"
address string "internal"
exchangeName string The name of the exchange where the transfer will occur between users
currency string Currency
amount string(double) Transfer amount
error Error A human-readable error message

Users

CreateUser

Create a user

Create User Request

import requests

post_body = {
  'permission_level': 'ADMIN'
}

r = requests.post(base_url + '/v1/users', json=post_body, auth=auth)
print(r.json())
public static void createUserExample(FPGRequest request) {Map<String, String> map = new HashMap<>() {
            {
                put("permission_level", "ADMIN");
            }
        };
    JSONObject postBody = new JSONObject(map);

    HttpResponse<String> response = request.doPOSTRequest("/v1/users", postBody.toString());
    System.out.println(response.body());
}
const request = require('request');

const postBody = {"permission_level": "ADMIN"};
const pathUrl = '/v1/users';

request.post(pathUrl, postOption(pathUrl, postBody), function (error, response, body) {
    console.log(body);
});

POST /v1/users

Parameters

Name In Type Required Description
permissionLevel body string False Permission level for the User: Default is TRADER

Response

{
"user": {
  "name": "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b",
  "tenant": "fpg",
  "permissionLevel": "ADMIN",
  "keys": [
      {
        "name": "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b/keys/8e18b0fd-0e35-4d73-b86a-7b090dd0294b",
        "publicKey": "3da93a46-64b0-453a-9755-3e911f889bf3",
        "secret": "5c66af0f-66cd-4597-b975-91762c0de5f2",
        "description": "Example key"
      }
    ]
  }
}

Response

Field Type Description
user string User
error Error A human-readable error message

GetUser

Get a user

Get User Request

import requests

user = 'users/21c482ec-d87b-4f5d-9b85-3aa6228f018b'

r = requests.get(base_url + f'/v1/{user}', auth=auth)
print(r.json())
public static void getUserExample(FPGRequest request) {
    String user = "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b";

    HttpResponse<String> response = request.doGETRequest(String.format("/v1/%s", user));
    System.out.println(response.body());
}
const request = require('request');

const user = 'users/21c482ec-d87b-4f5d-9b85-3aa6228f018b';
const pathUrl = `/v1/${user}`;

request.get(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

GET /v1/{user=users/*}

Parameters

Name In Type Required Description
user query string True A user

Response

{
"user": {
  "name": "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b",
  "tenant": "fpg",
  "permissionLevel": "ADMIN",
  "keys": [
      {
        "name": "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b/keys/8e18b0fd-0e35-4d73-b86a-7b090dd0294b",
        "publicKey": "3da93a46-64b0-453a-9755-3e911f889bf3",
        "secret": "5c66af0f-66cd-4597-b975-91762c0de5f2",
        "description": "Example key"
      },
      ...
    ]
  }
}

Response

Field Type Description
user User Name of a user
error Error A human-readable error message

ListUsers

List users

List Users Request

import requests

r = requests.get(base_url + f'/v1/users', auth=auth)
print(r.json())
public static void listUsersExample(FPGRequest request) {
    HttpResponse<String> response = request.doGETRequest("/v1/users");
    System.out.println(response.body());
}
const request = require('request');

const pathUrl = '/v1/users';

request.get(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

GET /v1/users

Parameters

Name In Type Required Description
user query string True Name of a user
pageSize query number(integer) False The maximum number of users to return

Response

{
"users": [
  {
    "name": "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b",
    "tenant": "fpg",
    "permissionLevel": "ADMIN",
    "keys": [
      {
        "name": "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b/keys/8e18b0fd-0e35-4d73-b86a-7b090dd0294b",
        "publicKey": "3da93a46-64b0-453a-9755-3e911f889bf3",
        "secret": "5c66af0f-66cd-4597-b975-91762c0de5f2",
        "description": "Example key"
      },
      ...
    ]
    },
  {
    "name": "users/06947fbd-28ab-4066-9d4a-a94eeed5adfa",
    "tenant": "fpg",
    "permissionLevel": "ADMIN",
    "keys": [
      {
        "name": "users/06947fbd-28ab-4066-9d4a-a94eeed5adfa/keys/21b4b8fc-3e4b-7d7k-k8bl-hq02qkh231pb",
        "publicKey": "1bkkpi22-abkk-bipq-ac2j-xb91kyz89qrp",
        "secret": "18bnlpt6-5651-90a0-19a6-96bamu0ukpa2",
        "description": "Example key 2"
      },
      ...
    ]
  },
  ...
}

Response

Field Type Description
users List[User] List of users
error Error A human-readable error message

CreateKey

Create keypair for user

Create Key Request

import requests

user = 'users/21c482ec-d87b-4f5d-9b85-3aa6228f018b'

r = requests.post(base_url + f'/v1/{user}/keys', auth=auth)
print(r.json())
public static void createKeyExample(FPGRequest request) {
    String user = "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b";

    HttpResponse<String> response = request.doPOSTRequest(String.format("/v1/%s/keys", user), "");
    System.out.println(response.body());
}
const request = require('request');

const user = 'users/21c482ec-d87b-4f5d-9b85-3aa6228f018b';
const pathUrl = `/v1/${user}/keys`;

request.post(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

POST /v1/{user=users/*}/keys

Parameters

Name In Type Required Description
user query string True Name of a user
description body string False Description for key

Response

{
  "users": [
    {
      "key": {
        "name": "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b/keys/8e18b0fd-0e35-4d73-b86a-7b090dd0294b",
        "publicKey": "3da93a46-64b0-453a-9755-3e911f889bf3",
        "secret": "5c66af0f-66cd-4597-b975-91762c0de5f2",
        "description": "Example key"
      }
    }
  ]
}

Response

Field Type Description
key Key FPG API Key
error Error A human-readable error message

DeleteKey

Delete key for user

Delete Key Request

import requests

key = 'users/21c482ec-d87b-4f5d-9b85-3aa6228f018b/keys/8e18b0fd-0e35-4d73-b86a-7b090dd0294b'

r = requests.delete(base_url + f'/v1/{key}', auth=auth)
print(r.json())
public static void deleteKeyExample(FPGRequest request) {
    String key = "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b/keys/8e18b0fd-0e35-4d73-b86a-7b090dd0294b";

    HttpResponse<String> response = request.doDELETERequest(String.format("/v1/%s", key));
    System.out.println(response.body());
}
const request = require('request');

const key = 'users/21c482ec-d87b-4f5d-9b85-3aa6228f018b/keys/8e18b0fd-0e35-4d73-b86a-7b090dd0294b';
const pathUrl = `/v1/${key}`;

request.delete(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

DELETE /v1/{key=users/*/keys/*}

Parameters

Name In Type Required Description
key query string True Name of a user's key

Response

{
  "key": {
    "name": "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b/keys/8e18b0fd-0e35-4d73-b86a-7b090dd0294b",
    "publicKey": "3da93a46-64b0-453a-9755-3e911f889bf3",
    "secret": "5c66af0f-66cd-4597-b975-91762c0de5f2",
    "description": "Example key"
  }
}

Response

Field Type Description
key Key FPG API Key
error Error A human-readable error message

ListKeys

List keys for user

List Keys Request

import requests

user = 'users/21c482ec-d87b-4f5d-9b85-3aa6228f018b'

r = requests.get(base_url + f'/v1/{user}/keys', auth=auth)
print(r.json())
public static void listKeysExample(FPGRequest request) {
    String user = "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b";

    HttpResponse<String> response = request.doGETRequest(String.format("/v1/%s/keys", user));
    System.out.println(response.body());
}
const request = require('request');

const user = 'users/21c482ec-d87b-4f5d-9b85-3aa6228f018b';
const pathUrl = `/v1/${user}/keys`;

request.get(pathUrl, option(pathUrl), function (error, response, body) {
    console.log(body);
});

GET /v1/{user=users/*}/keys

Parameters

Name In Type Required Description
user query string True Name of a user
pageSize query number(integer) False The maximum number of orders to return

Response

{
  "keys": {
    "name": "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b/keys/8e18b0fd-0e35-4d73-b86a-7b090dd0294b",
    "publicKey": "3da93a46-64b0-453a-9755-3e911f889bf3",
    "secret": "5c66af0f-66cd-4597-b975-91762c0de5f2",
    "description": "Example key"
  },
  ...
}

Response

Field Type Description
keys Key List of FPG API Keys
error Error A human-readable error message

Types

Exchange Markets

{
  "name": "BINANCE",
  "symbols": [
    "VIB-BTC",
    "ERD-BTC",
    "KEY-USDT",
    "DASH-BNB"
  ]
}

Properties

Field Type Description
name string name of the exchange
symbols List[string] List of market symbols available to be queried. A market symbol is represented as {base}-{quote}
error Error A human-readable error message

Orderbook

{
  "id": "659482",
  "level": "ORDERBOOK_LEVEL_TWO",
  "exchangeName": "BINANCE",
  "baseQuote": "ETH-BTC",
  "updateType": "ORDERBOOK_UPDATE_TYPE_SNAPSHOT",
  "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 string false ORDERBOOK_LEVEL_TWO Order book level
exchangeName string false none none
baseQuote string false none none
updateType string false ORDERBOOK_UPDATE_TYPE_SNAPSHOT Order book update type
timestamp string(datetime) false none Latest timestamp produced by the consolidated exchanges
sequenceHigh string(uint64) false none none
sequenceLow string(uint64) false none none
bids List[OrderbookEntry] false none Bids, descending
asks List[OrderbookEntry] false none Asks, ascending

OrderbookEntry

{
  "price": "240.46",
  "size": "1.125",
  "exchangeName": "COINBASEPRO"
}

Properties

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

Balance

{
  "balance": {
    "coinbasepro": {
      "currencies": {
        "USDC": {
          "free": "1000",
          "total": "1000"
        }, 
        "EUR": {
          "free": "1000",
          "total": "1000"
        }, 
        "BTC": {
          "free": "992371.3043",
          "used": "70.3888",
          "total": "992441.6931"
        }, 
        "ETH": {
          "free": "1000",
          "total": "1000"
        }, 
        "USD": {
          "free": "7376.89",
          "total": "7376.89"
        }
      }
    }
  }
}

Properties

Name Type Required Restrictions Description
currencies map<string,CurrencyBalance> true none Balance of currency at specific exchange

Currency Balance

{
  "BTC": {
    "free": "992371.3043",
    "used": "70.3888",
    "total": "992441.6931"
  } 
}

Properties

Name Type Required Restrictions Description
free string(double) true none Amount of free currency
used string(double) true none Amount of used currency
total string(double) true none Amount of total currency

User

{
  "name": "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b",
  "tenant": "fpg",
  "permissionLevel": "ADMIN",
  "keys": [
    {
      "name": "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b/keys/8e18b0fd-0e35-4d73-b86a-7b090dd0294b",
      "publicKey": "3da93a46-64b0-453a-9755-3e911f889bf3",
      "secret": "5c66af0f-66cd-4597-b975-91762c0de5f2",
      "description": "Example key"

    },
    ...
  ]
}

Properties

Name Type Required Restrictions Description
name string true none User ID
createdTime string true none Time that the user was created in our system
permissionLevel string true FPGADMIN, ADMIN, TRADER, ACCOUNTANT Level of API permissions
keys string true none API Key owned by user

Key

{
  "name": "users/21c482ec-d87b-4f5d-9b85-3aa6228f018b/keys/8e18b0fd-0e35-4d73-b86a-7b090dd0294b",
  "publicKey": "3da93a46-64b0-453a-9755-3e911f889bf3",
  "secret": "5c66af0f-66cd-4597-b975-91762c0de5f2",
  "description": "Example key"
}

Properties

Name Type Required Restrictions Description
name string true none Key ID
publicKey string true none Public key
secret string true none Secret key
description string false none Description for key

Order

Submitting Order

{
  "name": "orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a",
  "userName": "users/fizz",
  "createdTime": "2019-05-14T19:57:38.123Z",
  "status": "FPGOS_SUBMITTING",
  "base": "BTC",
  "quote": "USD",
  "size": "6",
  "price": "5000",
  "algo": "ACTIVELIMIT",
  "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",
}

Running Order

{
  "name": "orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a",
  "userName": "users/fizz",
  "createdTime": "2019-05-14T19:57:38.123Z",
  "status": "FPGOS_RUNNING",
  "base": "BTC",
  "quote": "USD",
  "size": "6",
  "price": "5000",
  "algo": "ACTIVELIMIT",
  "orderType": "BUY",
  "exchangeNames": [
    "KRAKEN", "GEMINI"
  ],
  "executionAveragePrice": "4150.5",
  "executionCost": "15000",
  "executionSize": "3",
  "executionFee": "20",
  "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"
}

An Order is placed by the client and fulfilled by FPG. These Orders are not submitted directly to the exchanges. FPG uses the requested algorithm to generate a series of Suborders, which are then submitted to the exchanges. When the Suborders are fufilled by the exchanges, FPG uses that data to update the Order associated with that Suborder. When all Suborders associated with a given Order are completely filled by the exchange, the given Order will be considered Completed.

An Order Status is Submitting starting from when FPG recieves the request until the time when all associated suborders have been created. The Order Status is then Running until: all of the Suborders are completed, in which it is then Complete; FPG is unable to fill an it for any reason, in which case it is Failed; or a request is recieved to cancel it, in which case it is PendingCancel until all suborders have been cancelled, then it is Cancelled.

Properties

Name Type Required Restrictions Description
name string false Must begin with "orders/" Name of the order
userName string false Must begin with "users/" Name of user submitting the order
createdTime string false Must be greater than 0 Time that the order started on our system
status string false SUBMITTING, RUNNING, COMPLETE, PENDING_CANCEL, CANCELLED, FAILED Status of the order
base string true Exchange dependent Base currency
quote string true Exchange dependent Quote currency
size string(double) true Must be greater than 0 Requested size of the order
price string(double) false Must be greater than 0 Price limit of an order
algo string false DMA, DMA2, ACTIVEMARKET, ACTIVELIMIT, PASSIVE, TWAP, VWAP Algorithm used to generate and execute Suborders
orderType string true BUY, SELL Order type
exchangeNames List[string] true Binance, Coinbase Pro, Kraken, Gemini Names of exchanges to route orders
executionAveragePrice string(double) false none Average price (in quote) of trades constituting order
executionCost string(double) false none Quantity of quote currency traded
executionSize string(double) false none Quantity of base currency traded
executionFee string(double) false none Quantity of currency (in quote) taken by exchange as a fee
expectedStartTime string(datetime) false Must be greater than current time Time execution expected to start
expectedEndTime string(datetime) false Must be greater than current time Time execution expected to end
executionStartTime string(datetime) false Must be greater than current time Actual execution start time
executionEndTime string(datetime) false Must be greater than current time Actual execution end time

SubOrder

Scheduled 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": "ACTIVELIMIT",
  "orderType": "BUY",
  "exchangeName": "KRAKEN",
  "expectedSize": "5",
  "expectedPrice": "5000",
  "expectedStartTime": "2019-05-14T19:57:38.123Z",
  "expectedEndTime": "2019-05-14T19:57:38.123Z",
}

Complete Suborder

{
  "name": "orders/af0a83a7-4a39-4f80-a607-4b50c3046e5a/suborders/ae6a5449-ff00-486a-835a-702eee9cba37",
  "createdTime": "2019-05-14T19:57:38.123Z",
  "status": "FPGEOS_COMPLETE",
  "base": "BTC",
  "quote": "USD",
  "algo": "ACTIVELIMIT",
  "orderType": "BUY",
  "exchangeName": "KRAKEN",
  "expectedSize": "5",
  "expectedPrice": "5000",
  "executionSize": "5",
  "executionAveragePrice": "4879.89",
  "executionFee": "20",
  "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": "orderID123"
}

Properties

Name Type Required Restrictions Description
name string true Must be of form "orders/{order_id}/suborders/{suborder_id} Name of the suborder
createdTime string(datetime) false Must be greater than 0 Time that the order started on our system
status string false 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, DMA2, ACTIVEMARKET, ACTIVELIMIT, PASSIVE, TWAP, VWAP Algorithm used to generate and execute the suborder
orderType string false BUY, SELL The order type on the exchange
exchangeName string false One of exchanges specified in parent order Exchange suborder is executed on
executionAveragePrice string(double) false none Average price (in quote) of trades constituting order
executionSize string(double) false none Quantity of base currency traded
executionFee string(double) false none Quantity of currency (in quote) taken by exchange as a fee
expectedStartTime string(datetime) false Must be greater than current time Time execution expected to start
expectedEndTime string(datetime) false Must be greater than current time Time execution expected to end
executionStartTime string(datetime) false Must be greater than current time Actual execution start time
executionEndTime string(datetime) false Must be greater than current time Actual execution end time
exchangeOrderId string false none Name asigned to suborder when submitted to exchange

WithdrawAddress

{
  "address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", 
  "tag": "34685394543", 
  "address_key": "test_key", 
  "currency": "ETH"
}

A WithdrawAddress is an address saved/whitelisted by the user. The user can later fetch all the white listed addresses and use them to withdraw as needed.

Properties

Name Type Required Description
address string true address string for the whitelisted address
currency string true currency associated with this address
tag string false tag for the whitelisted address for currencies like 'XRP'
address_key string false address_key identifier for identifying withdrawal address. Currently this is needed only for addresses for kraken exchange

Error

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

An error returned by the server. The StatusCode field is intentionally omitted because there's already one included in the 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. If you would like to make the trade as you specified, you can use DMA.

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

Schedule-driven includes TWAP and VWAP.

Evaluative includes Passive.

Opportunistic includes ActiveMarket and ActiveLimit.

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 string(double) false none Price limit of an order
size string(double) true none Requested size of the order
expectedStartTime string(datetime) false Must be greater than current time Time expected to start executing
expectedEndTime string(datetime) false Must be greater than current time Time expected to end execution
exchangeNames List[string] true Binance, Coinbase Pro, Kraken, 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 string(double) false none Price limit of an order
size string(double) true none Requested size of the order
expectedStartTime string(datetime) false Must be greater than current time Time expected to start executing
expectedEndTime string(datetime) false Must be greater than current time Time expected to end execution
exchangeNames List[string] true Binance, Coinbase Pro, Kraken, 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 string(double) false none Price limit of an order
size string(double) true none Requested size of the order
expectedStartTime string(datetime) false Must be greater than current time Time expected to start executing
expectedEndTime string(datetime) false Must be greater than current time Time expected to end execution
exchangeNames List[string] true Binance, Coinbase Pro, Kraken, Gemini Names of exchanges to route orders
base string true Exchange dependent Base currency
quote string true Exchange dependent Quote currency

ActiveMarket

The algorithm will aggressively trade and will cross to the other side of the order book to fulfill the order in the fastest time possible. If an expectedEndTime is specified, 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
size string(double) true none Requested size of the order
expectedStartTime string(datetime) false Must be greater than current time Time expected to start executing
expectedEndTime string(datetime) No none Order will increase price linearly by aggression*(execution_size)/(expectedEndTime-expectedStartTime).
exchangeNames List[string] true Binance, Coinbase Pro, Kraken, 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

ActiveLimit

The algorithm will aggressively trade and will cross the order books to fulfill the order in the fastest time possible while staying below the target price. If an expectedEndTime 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 string(double) false none Price limit of an order
size string(double) true none Requested size of the order
expectedStartTime string(datetime) false Must be greater than current time Time expected to start executing
expectedEndTime string(datetime) No none Order will increase price linearly by aggression*(execution_size)/(expectedEndTime-expectedStartTime).
exchangeNames List[string] true Binance, Coinbase Pro, Kraken, 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.