Introduction

Welcome to GDAX trader and developer documentation. These documents outline exchange functionality, market details, and APIs.

APIs are separated into two categories: trading and feed. Trading APIs require authentication and provide access to placing orders and other account information. Feed APIs provide market data and are public.

General

Market overview and general information.

Matching Engine

GDAX operates a continuous first-come, first-serve order book. Orders are executed in price-time priority as received by the matching engine.

Self-Trade Prevention

Self-trading is not allowed on GDAX. Two orders from the same user will not fill one another. When placing an order, you can specify the self-trade prevention behavior.

Decrement and cancel

The default behavior is decrement and cancel. When two orders from the same user cross, the smaller order will be canceled and the larger order size will be decremented by the smaller order size. If the two orders are the same size, both will be canceled.

Cancel oldest

Cancel the older (resting) order in full. The new order continues to execute.

Cancel newest

Cancel the newer (taking) order in full. The old resting order remains on the order book.

Cancel both

Immediately cancel both orders.

Notes for Market Orders

When a market order using dc self-trade prevention encounters an open limit order, the behavior depends on which fields for the market order message were specified. If funds and size are specified for a buy order, then size for the market order will be decremented internally within the matching engine and funds will remain unchanged. The intent is to offset your target size without limiting your buying power. If size is not specified, then funds will be decremented. For a market sell, the size will be decremented when encountering existing limit orders.

Price Improvement

Orders are matched against existing order book orders at the price of the order on the book, not at the price of the taker order.

Example

User A places a Buy order for 1 BTC at 100 USD. User B then wishes to sell 1 BTC at 80 USD. Because User A’s order was first to the trading engine, they will have price priority and the trade will occur at 100 USD.

Order Lifecycle

Valid orders sent to the matching engine are confirmed immediately and are in the received state. If an order executes against another order immediately, the order is considered done. An order can execute in part or whole. Any part of the order not filled immediately, will be considered open. Orders will stay in the open state until canceled or subsequently filled by new orders. Orders that are no longer eligible for matching (filled or canceled) are in the done state.

Fees

Trading Fees

GDAX operates a maker-taker model. Orders which provide liquidity are charged different fees from orders taking liquidity. The fee is assessed as a percentage of the match amount (price * size).

User 30 day volume % Taker fee Maker fee
> 0 % 0.25 % * 0 %
> 1 % 0.24 % 0 %
> 2.5 % 0.22 % 0 %
> 5 % 0.19 % 0 %
> 10% 0.15 % 0 %
> 20 % 0.10 % 0 %

A 0.25% taker fee is collected on each trade during the day. At the end of the day (UTC 00:00), a rebate is calculated and issued. The amount of the rebate issued is calculated on the percentage of total exchange volume, in bitcoin, that a trader has participated in over the past 30 days.

  • ETH & LTC markets have a 0.3% taker fee at the 0-1% volume level.

Example

There is an existing SELL order for 5 BTC at 100 USD on the order book. You enter a BUY order for 7 BTC at 100 USD. 5 BTC of your BUY order are immediately matched and you are charged the taker fee because you are taking liquidity from the order book. The remaining 2 BTC of your order are now sitting on the BID side of the order book. A SELL order for 2 BTC at 100 USD arrives and matches against your 2 BTC BUY order. In this case you provided liquidity and are not charged any fees.

Rebate example

If 100 BTC was traded on Coinbase’s USD order book in the last thirty days and you accounted for 1.1 bitcoin, you account for more than 1% of the total volume and receive a rebate of 0.01% that day and pay an effective taker fee of 0.24%.

The rebate is issued in the quote currency.

Deposit/Withdraw Fees

GDAX does not charge any additional deposit or withdraw fees for moving funds between your Coinbase accounts and your Exchange accounts.

Colocation

GDAX primary data sources and servers run in the Amazon US East N. Virginia data center. To minimize latency for API access, we recommend making requests from servers located near the AWS us-east-1 data center.

Sandbox

A public sandbox is available for testing API connectivity and web trading. The sandbox provides all of the functionality of the production exchange but allows you to add fake funds for testing.

Login sessions and API keys are separate from production. Use the sandbox web interface to create keys in the sandbox environment.

To add funds, use the web interface deposit and withdraw buttons as you would on the production web interface.

Sandbox URLs

When testing your API connectivity, make sure to use the following URLs.

Website
https://public.sandbox.gdax.com

REST API
https://api-public.sandbox.gdax.com

Websocket Feed
wss://ws-feed-public.sandbox.gdax.com

FIX API
https://fix-public.sandbox.gdax.com

Note on FIX API

var https = require('https');
var request = https.request({
    method: 'GET',
    url: 'https://fix-public.sandbox.gdax.com',
    headers: {
        Upgrade: 'fix',
        Connection: 'Upgrade'
    }
});

request.on('upgrade', function(req, socket, head) {
    // Pass socket to FIX client
});

request.end();

When connecting to the FIX API in Sandbox, you must start with an HTTP Upgrade request and set the Upgrade header to fix. After receiving a 101 Switching Protocols response from the server, you may continue using the connection as a regular FIX connection. Remember to use HTTPS for this.

Client Libraries

Client libraries can help you integrate with our API quickly.

Official

Unofficial

API

The REST API has endpoints for account and order management as well as public market data.

REST API Endpoint URL

https://api.gdax.com

There is also a FIX API for order management.

Requests

All requests and responses are application/json content type and follow typical HTTP response status codes for success and failure.

Errors

{
    "message": "Invalid Price"
}

Unless otherwise stated, errors to bad requests will respond with HTTP 4xx or status codes. The body will also contain a message parameter indicating the cause. Your language’s http library should be configured to provide message bodies for non-2xx requests so that you can read the message field from the body.

Common error codes

Status Code Reason
400 Bad Request – Invalid request format
401 Unauthorized – Invalid API Key
403 Forbidden – You do not have access to the requested resource
404 Not Found
500 Internal Server Error – We had a problem with our server

Success

A successful response is indicated by HTTP status code 200 and may contain an optional body. If the response has a body it will be documented under each resource below.

Pagination

GDAX uses cursor pagination for all REST requests which return arrays. Cursor pagination allows for fetching results before and after the current page of results and is well suited for realtime data. Endpoints like /trades, /fills, /orders, return the latest items by default. To retrieve more results subsequent requests should specify which direction to paginate based on the data previously returned.

before and after cursors are available via response headers CB-BEFORE and CB-AFTER. Your requests should use these cursor values when making requests for pages after the initial request.

Parameters

Parameter Default Description
before Request page before (newer) this pagination id.
after Request page after (older) this pagination id.
limit 100 Number of results per request. Maximum 100. (default 100)

Example

GET /orders?before=2&limit=30

Before and After cursors

The before cursor references the first item in a results page and the `after cursor references the last item in a set of results.

To request a page of records before the current one, use the before query parameter. Your initial request can omit this parameter to get the default first page.

The response will contain a CB-BEFORE header which will return the cursor id to use in your next request for the page before the current one. The page before is a newer page and not one that happened before in chronological time.

The response will also contain a CB-AFTER header which will return the cursor id to use in your next request for the page after this one. The page after is an older page and not one that happened after this one in chronological time.

Types

Timestamps

2014-11-06T10:34:47.123456Z

Unless otherwise specified, all timestamps from API are returned in ISO 8601 with microseconds. Make sure you can parse the following ISO 8601 format. Most modern languages and libraries will handle this without issues.

Numbers

Decimal numbers are returned as strings to preserve full precision across platforms. When making a request, it is recommended that you also convert your numbers to strings to avoid truncation and precision errors.

Integer numbers (like trade id and sequence) are unquoted.

IDs

Most identifiers are UUID unless otherwise specified. When making a request which requires a UUID, both forms (with and without dashes) are accepted.

132fb6ae-456b-4654-b4e0-d681ac05cea1 or 132fb6ae456b4654b4e0d681ac05cea1

Rate Limits

When a rate limit is exceeded, a status of 429 Too Many Requests will be returned.

REST API

Public endpoints

We throttle public endpoints by IP: 3 requests per second, up to 6 requests per second in bursts.

Private endpoints

We throttle private endpoints by user ID: 5 requests per second, up to 10 requests per second in bursts.

Financial Information eXchange API

The FIX API throttles each command type (eg.: NewOrderSingle, OrderCancelRequest) to 50 commands per second.

Margin Trading

GDAX offers margin trading. To trade with margin you must use a sub account we call a margin profile. The margin profile is completely separate from the default/standard profile and can only be used on a single product. To trade with margin on multiple products you must use a different profile for each product. Margin profiles still enforce self trade prevention. Self trade prevention is enforced at the user level. This means your margin profiles and your standard profile cannot trade against each other.

To create a margin profile, toggle margin on for your desired product on our web interface at www.gdax.com/trade.

After your margin profile is created you can generate an API key for your desired margin profile at www.gdax.com/settings/api. Note, you will need the manage permission to be able to transfer funds to and from your margin profile.

With the margin profile’s api key you can now deposit funds from the standard profile to the margin profile.

With some margin in the margin profile’s balance you can place orders that draw funding. You can draw upto 2x your margin. Your margin is your equity in the margin profile.

[Your margin] = [value of margin profile's balances] - [value of funding]

When you place an order that draws funding, a funding record is created. A funding record must be repaid after 27 days and 22 hours or we will rebalance your profile to repay the funding.

While trading you can monitor your margin profile by subscribing to the authenticated websocket feed and querying GET /position.

Private

Private endpoints are available for order management, and account management. Every private request must be signed using the described authentication scheme.

Authentication

Generating an API Key

Before being able to sign any requests, you must create an API key via the GDAX website. If you are eligible for margin you may select to generate an API key for either your default profile, or your margin profile. Upon creating a key you will have 3 pieces of information which you must remember:

  • Key
  • Secret
  • Passphrase

The Key and Secret will be randomly generated and provided by GDAX; the Passphrase will be provided by you to further secure your API access. GDAX stores the salted hash of your passphrase for verification, but cannot recover the passphrase if you forget it.

Creating a Request

All REST requests must contain the following headers:

  • CB-ACCESS-KEY The api key as a string.
  • CB-ACCESS-SIGN The base64-encoded signature (see Signing a Message).
  • CB-ACCESS-TIMESTAMP A timestamp for your request.
  • CB-ACCESS-PASSPHRASE The passphrase you specified when creating the API key.

All request bodies should have content type application/json and be valid JSON.

Signing a Message

var crypto = require('crypto');

var secret = 'PYPd1Hv4J6/7x...';

var timestamp = Date.now() / 1000;
var requestPath = '/orders';

var body = JSON.stringify({
    price: '1.0',
    size: '1.0',
    side: 'buy',
    product_id: 'BTC-USD'
});

var method = 'POST';

// create the prehash string by concatenating required parts
var what = timestamp + method + requestPath + body;

// decode the base64 secret
var key = Buffer(secret, 'base64');

// create a sha256 hmac with the secret
var hmac = crypto.createHmac('sha256', key);

// sign the require message with the hmac
// and finally base64 encode the result
return hmac.update(what).digest('base64');
# Requires python-requests. Install with pip:
#
#   pip install requests
#
# or, with easy-install:
#
#   easy_install requests

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

# Create custom authentication for Exchange
class CoinbaseExchangeAuth(AuthBase):
    def __init__(self, api_key, secret_key, passphrase):
        self.api_key = api_key
        self.secret_key = secret_key
        self.passphrase = passphrase

    def __call__(self, request):
        timestamp = str(time.time())
        message = timestamp + request.method + request.path_url + (request.body or '')
        hmac_key = base64.b64decode(self.secret_key)
        signature = hmac.new(hmac_key, message, hashlib.sha256)
        signature_b64 = signature.digest().encode('base64').rstrip('\n')

        request.headers.update({
            'CB-ACCESS-SIGN': signature_b64,
            'CB-ACCESS-TIMESTAMP': timestamp,
            'CB-ACCESS-KEY': self.api_key,
            'CB-ACCESS-PASSPHRASE': self.passphrase,
            'Content-Type': 'application/json'
        })
        return request

api_url = 'https://api.gdax.com/'
auth = CoinbaseExchangeAuth(API_KEY, API_SECRET, API_PASS)

# Get accounts
r = requests.get(api_url + 'accounts', auth=auth)
print r.json()
# [{"id": "a1b2c3d4", "balance":...

# Place an order
order = {
    'size': 1.0,
    'price': 1.0,
    'side': 'buy',
    'product_id': 'BTC-USD',
}
r = requests.post(api_url + 'orders', json=order, auth=auth)
print r.json()
# {"id": "0428b97b-bec1-429e-a94c-59992926778d"}
require 'base64'
require 'openssl'
require 'json'

class CoinbaseExchange
    def initialize(key, secret, passphrase)
      @key = key
      @secret = secret
      @passphrase = passphrase
    end

    def signature(request_path='', body='', timestamp=nil, method='GET')
      body = body.to_json if body.is_a?(Hash)
      timestamp = Time.now.to_i if !timestamp

      what = "#{timestamp}#{method}#{request_path}#{body}";

      # create a sha256 hmac with the secret
      secret = Base64.decode64(@secret)
      hash  = OpenSSL::HMAC.digest('sha256', secret, what)
      Base64.strict_encode64(hash)
    end
end
<?php
class CoinbaseExchange {
    public function __construct($key, $secret, $passphrase) {
        $this->key = $key;
        $this->secret = $secret;
        $this->passphrase = $passphrase;
    }

    public function signature($request_path='', $body='', $timestamp=false, $method='GET') {
        $body = is_array($body) ? json_encode($body) : $body;
        $timestamp = $timestamp ? $timestamp : time();

        $what = $timestamp.$method.$request_path.$body;

        return base64_encode(hash_hmac("sha256", $what, base64_decode($this->secret), true));
    }
}

The CB-ACCESS-SIGN header is generated by creating a sha256 HMAC using the base64-decoded secret key on the prehash string timestamp + method + requestPath + body (where + represents string concatenation) and base64-encode the output. The timestamp value is the same as the CB-ACCESS-TIMESTAMP header.

The body is the request body string or omitted if there is no request body (typically for GET requests).

The method should be UPPER CASE.

Selecting a Timestamp

The CB-ACCESS-TIMESTAMP header MUST be number of seconds since Unix Epoch in UTC. Decimal values are allowed.

Your timestamp must be within 30 seconds of the api service time or your request will be considered expired and rejected. We recommend using the time endpoint to query for the API server time if you believe there many be time skew between your server and the API servers.

Accounts

List Accounts

[
    {
        "id": "71452118-efc7-4cc4-8780-a5e22d4baa53",
        "currency": "BTC",
        "balance": "0.0000000000000000",
        "available": "0.0000000000000000",
        "hold": "0.0000000000000000",
        "profile_id": "75da88c5-05bf-4f54-bc85-5c775bd68254"
    },
    {
        "id": "e316cb9a-0808-4fd7-8914-97829c1925de",
        "currency": "USD",
        "balance": "80.2301373066930000",
        "available": "79.2266348066930000",
        "hold": "1.0035025000000000",
        "profile_id": "75da88c5-05bf-4f54-bc85-5c775bd68254"
    }
]

Get a list of trading accounts.

Http Request

GET /accounts

Account Fields

Field Description
id Account ID
currency the currency of the account
balance total funds in the account
holds funds on hold (not available for use)
available funds available to withdraw* or trade
margin_enabled [margin] true if the account belongs to margin profile
funded_amount [margin] amount of funding GDAX is currently providing this account
default_amount [margin] amount defaulted on due to not being able to pay back funding

* Only applicable to non margin accounts. Withdraws on margin accounts are subject to other restrictions.

Funds on Hold

When you place an order, the funds for the order are placed on hold. They cannot be used for other orders or withdrawn. Funds will remain on hold until the order is filled or canceled.

Get an Account

{
    "id": "a1b2c3d4",
    "balance": "1.100",
    "holds": "0.100",
    "available": "1.00",
    "currency": "USD"
}

Information for a single account. Use this endpoint when you know the account_id.

Http request

GET /accounts/<account-id>

Account Fields

Field Description
id Account ID
balance total funds in the account
holds funds on hold (not available for use)
available funds available to withdraw* or trade
margin_enabled [margin] true if the account belongs to margin profile
funded_amount [margin] amount of outstanding funds currently credited to the account
default_amount [margin] amount defaulted on due to not being able to pay back funding

* Only applicable to non margin accounts. Withdraws on margin accounts are subject to other restrictions.

Get Account History

[
    {
        "id": "100",
        "created_at": "2014-11-07T08:19:27.028459Z",
        "amount": "0.001",
        "balance": "239.669",
        "type": "fee",
        "details": {
            "order_id": "d50ec984-77a8-460a-b958-66f114b0de9b",
            "trade_id": "74",
            "product_id": "BTC-USD"
        }
    }
]

List account activity. Account activity either increases or decreases your account balance. Items are paginated and sorted latest first. See the Pagination section for retrieving additional entries after the first page.

Http request

GET /accounts/<account-id>/ledger

Entry Types

Entry type indicates the reason for the account change.

Type Description
transfer Funds moved to/from Coinbase to GDAX
match Funds moved as a result of a trade
fee Fee as a result of a trade
rebate Fee rebate as per our fee schedule

Details

If an entry is the result of a trade (match, fee), the details field will contain additional information about the trade.

Get Holds

[
    {
        "id": "82dcd140-c3c7-4507-8de4-2c529cd1a28f",
        "account_id": "e0b3f39a-183d-453e-b754-0c13e5bab0b3",
        "created_at": "2014-11-06T10:34:47.123456Z",
        "updated_at": "2014-11-06T10:40:47.123456Z",
        "amount": "4.23",
        "type": "order",
        "ref": "0a205de4-dd35-4370-a285-fe8fc375a273",
    }
]

Holds are placed on an account for any active orders or pending withdraw requests. As an order is filled, the hold amount is updated. If an order is canceled, any remaining hold is removed. For a withdraw, once it is completed, the hold is removed.

Http Request

GET /accounts/<account_id>/holds

Type

The type of the hold will indicate why the hold exists. The hold type is order for holds related to open orders and transfer for holds related to a withdraw.

Ref

The ref field contains the id of the order or transfer which created the hold.

Orders

Place a New Order

{
    "size": "0.01",
    "price": "0.100",
    "side": "buy",
    "product_id": "BTC-USD"
}

Response

{
    "id": "d0c5340b-6d6c-49d9-b567-48c4bfca13d2",
    "price": "0.10000000",
    "size": "0.01000000",
    "product_id": "BTC-USD",
    "side": "buy",
    "stp": "dc",
    "type": "limit",
    "time_in_force": "GTC",
    "post_only": false,
    "created_at": "2016-12-08T20:02:28.53864Z",
    "fill_fees": "0.0000000000000000",
    "filled_size": "0.00000000",
    "executed_value": "0.0000000000000000",
    "status": "pending",
    "settled": false
}

You can place different types of orders: limit, market, and stop. Orders can only be placed if your account has sufficient funds. Once an order is placed, your account funds will be put on hold for the duration of the order. How much and which funds are put on hold depends on the order type and parameters specified. See the Holds details below.

HTTP Request

POST /orders

Parameters

These parameters are common to all order types. Depending on the order type, additional parameters will be required (see below).

Param Description
client_oid [optional] Order ID selected by you to identify your order
type [optional] limit, market, or stop (default is limit)
side buy or sell
product_id A valid product id
stp [optional] Self-trade prevention flag

limit order parameters

Param Description
price Price per bitcoin
size Amount of BTC to buy or sell
time_in_force [optional] GTC, GTT, IOC, or FOK (default is GTC)
cancel_after [optional]* min, hour, day
post_only [optional]** Post only flag

* Requires time_in_force to be GTT

** Invalid when time_in_force is IOC or FOK

market order parameters

Param Description
size [optional]* Desired amount in BTC
funds [optional]* Desired amount of quote currency to use

* One of size or funds is required.

stop order parameters

Param Description
price Desired price at which the stop order triggers
size [optional]* Desired amount in BTC
funds [optional]* Desired amount of quote currency to use

* One of size or funds is required.

margin parameters

Param Description
overdraft_enabled * If true funding will be provided if the order’s cost cannot be covered by the account’s balance
funding_amount * Amount of funding to be provided for the order

* Margin can be used to receive funding by specifying either overdraft_enabled or funding_amount.

Product ID

The product_id must match a valid product. The products list is available via the /products endpoint.

Client Order ID

The optional client_oid field must be a UUID generated by your trading application. This field value will be broadcast in the public feed for received messages. You can use this field to identify your orders in the public feed.

The client_oid is different than the server-assigned order id. If you are consuming the public feed and see a received message with your client_oid, you should record the server-assigned order_id as it will be used for future order status updates. The client_oid will NOT be used after the received message is sent.

The server-assigned order id is also returned as the id field to this HTTP POST request.

Type

When placing an order, you can specify the order type. The order type you specify will influence which other order parameters are required as well as how your order will be executed by the matching engine. If type is not specified, the order will default to a limit order.

limit orders are both the default and basic order type. A limit order requires specifying a price and size. The size is the number of bitcoin to buy or sell, and the price is the price per bitcoin. The limit order will be filled at the price specified or better. A sell order can be filled at the specified price per bitcoin or a higher price per bitcoin and a buy order can be filled at the specified price or a lower price depending on market conditions. If market conditions cannot fill the limit order immediately, then the limit order will become part of the open order book until filled by another incoming order or canceled by the user.

market orders differ from limit orders in that they provide no pricing guarantees. They however do provide a way to buy or sell specific amounts of bitcoin or fiat without having to specify the price. Market orders execute immediately and no part of the market order will go on the open order book. Market orders are always considered takers and incur taker fees. When placing a market order you can specify funds and/or size. Funds will limit how much of your quote currency account balance is used and size will limit the bitcoin amount transacted.

stop orders become active and wait to trigger based on the movement of the last trade price. There are two types of stop orders, sell stop and buy stop.

The side parameter is important:

side: 'sell': Place a sell stop order, which triggers when the last trade price changes to a value at or below the price.

side: 'buy': Place a buy stop order, which triggers when the last trade price changes to a value at or above price.

The last trade price is the last price at which an order was filled. This price can be found in the latest match message. Note that not all match messages may be received due to dropped messages.

Note that when triggered, stop orders execute as market orders and are therefore subject to market order holds.

Price

The price must be specified in quote_increment product units. The quote increment is the smallest unit of price. For the BTC-USD product, the quote increment is 0.01 or 1 penny. Prices less than 1 penny will not be accepted, and no fractional penny prices will be accepted. Not required for market orders.

Size

The size must be greater than the base_min_size for the product and no larger than the base_max_size. The size can be in any increment of the base currency (BTC for the BTC-USD product), which includes satoshi units. size indicates the amount of BTC (or base currency) to buy or sell.

Funds

The funds field is optionally used for market orders. When specified it indicates how much of the product quote currency to buy or sell. For example, a market buy for BTC-USD with funds specified as 150.00 will spend 150 USD to buy BTC (including any fees). If the funds field is not specified for a market buy order, size must be specified and GDAX will use available funds in your account to buy bitcoin.

A market sell order can also specify the funds. If funds is specified, it will limit the sell to the amount of funds specified. You can use funds with sell orders to limit the amount of quote currency funds received.

Time in force

Time in force policies provide guarantees about the lifetime of an order. There are four policies: good till canceled GTC, good till time GTT, immediate or cancel IOC, and fill or kill FOK.

GTC Good till canceled orders remain open on the book until canceled. This is the default behavior if no policy is specified.

GTT Good till time orders remain open on the book until canceled or the allotted cancel_after is depleted on the matching engine. GTT orders are guaranteed to cancel before any other order is processed after the cancel_after timestamp which is returned by the API. A day is considered 24 hours.

IOC Immediate or cancel orders instantly cancel the remaining size of the limit order instead of opening it on the book.

FOK Fill or kill orders are rejected if the entire size cannot be matched.

* Note, match also refers to self trades.

Post only

The post-only flag indicates that the order should only make liquidity. If any part of the order results in taking liquidity, the order will be rejected and no part of it will execute.

Holds

For limit buy orders, we will hold price x size x (1 + fee-percent) USD. For sell orders, we will hold the number of Bitcoin you wish to sell. Actual fees are assessed at time of trade. If you cancel a partially filled or unfilled order, any remaining funds will be released from hold.

For market buy orders where funds is specified, the funds amount will be put on hold. If only size is specified, all of your account balance (in the quote account) will be put on hold for the duration of the market order (usually a trivially short time). For a sell order, the size in BTC will be put on hold. If size is not specified (and only funds is specified), your entire BTC balance will be on hold for the duration of the market order.

Self-trade prevention

Self-trading is not allowed on GDAX. Two orders from the same user will not be allowed to match with one another. To change the self-trade behavior, specify the stp flag.

Flag Name
dc Decrease and Cancel (default)
co Cancel oldest
cn Cancel newest
cb Cancel both

See the self-trade prevention documentation for details about these fields.

Margin

Orders placed with a margin profile can draw funding by either specifing funding_amount or setting overdraft_enabled to true. Funding can be drawn as long as the margin profile’s margin ratio remains above the intial margin ratio and your oustanding funds remain below your profile’s cap.

funding_amount

This is the amount of funding that you wish to be credited to your account at the time of order placement. For buy orders this value is denominated in the quote currency and for sell orders it is denominated in the base currency. On the BTC-USD product this would be USD for buy orders and BTC for sell orders. The funding amount cannot be larger than the cost of the order.

overdraft_enabled

If set to true we will automatically determine funding_amount such that you can place the order. If you have enough funds to cover the order in your account, funding_amount will be 0. If you do not have enough funds to cover the order’s cost, we will set funding_amount to be the difference. For example if you have 100 USD in your margin account and place a post only limit order to buy 2 BTC @ 800 USD, we will set funding_amount to be 2 * 800 - 100 = 1500 USD.

Order Lifecycle

The HTTP Request will respond when an order is either rejected (insufficient funds, invalid parameters, etc) or received (accepted by the matching engine). A 200 response indicates that the order was received and is active. Active orders may execute immediately (depending on price and market conditions) either partially or fully. A partial execution will put the remaining size of the order in the open state. An order that is filled completely, will go into the done state.

Users listening to streaming market data are encouraged to use the client_oid field to identify their received messages in the feed. The REST response with a server order_id may come after the received message in the public data feed.

Response

A successful order will be assigned an order id. A successful order is defined as one that has been accepted by the matching engine.

Cancel an Order

Cancel a previously placed order.

If the order had no matches during its lifetime its record may be purged. This means the order details will not be available with GET /orders/<order-id>.

HTTP Request

DELETE /orders/<order-id>

Cancel Reject

If the order could not be canceled (already filled or previously canceled, etc), then an error response will indicate the reason in the message field.

Cancel all

With best effort, cancel all open orders. The response is a list of ids of the canceled orders.

[
    "144c6f8e-713f-4682-8435-5280fbe8b2b4",
    "debe4907-95dc-442f-af3b-cec12f42ebda",
    "cf7aceee-7b08-4227-a76c-3858144323ab",
    "dfc5ae27-cadb-4c0c-beef-8994936fde8a",
    "34fecfbf-de33-4273-b2c6-baf8e8948be4"
]

HTTP Request

DELETE /orders

Query Parameters

Param Default Description
product_id [optional] Only cancel orders open for a specific product

List Orders

[
    {
        "id": "d0c5340b-6d6c-49d9-b567-48c4bfca13d2",
        "price": "0.10000000",
        "size": "0.01000000",
        "product_id": "BTC-USD",
        "side": "buy",
        "stp": "dc",
        "type": "limit",
        "time_in_force": "GTC",
        "post_only": false,
        "created_at": "2016-12-08T20:02:28.53864Z",
        "fill_fees": "0.0000000000000000",
        "filled_size": "0.00000000",
        "executed_value": "0.0000000000000000",
        "status": "open",
        "settled": false
    },
    {
        "id": "8b99b139-58f2-4ab2-8e7a-c11c846e3022",
        "price": "1.00000000",
        "size": "1.00000000",
        "product_id": "BTC-USD",
        "side": "buy",
        "stp": "dc",
        "type": "limit",
        "time_in_force": "GTC",
        "post_only": false,
        "created_at": "2016-12-08T20:01:19.038644Z",
        "fill_fees": "0.0000000000000000",
        "filled_size": "0.00000000",
        "executed_value": "0.0000000000000000",
        "status": "open",
        "settled": false
    }
]

List your current open orders. Only open or un-settled orders are returned. As soon as an order is no longer open and settled, it will no longer appear in the default request.

HTTP REQUEST

GET /orders

Query Parameters

Param Default Description
status [open, pending, active] Limit list of orders to these statuses. Passing all returns orders of all statuses.
product_id [optional] Only list orders for a specific product

To specify multiple statuses, use the status query argument multiple times: /orders?status=done&status=pending.

Order status and settlement

Orders which are no longer resting on the order book, will be marked with the done status. There is a small window between an order being done and settled. An order is settled when all of the fills have settled and the remaining holds (if any) have been removed.

Polling

For high-volume trading it is strongly recommended that you maintain your own list of open orders and use one of the streaming market data feeds to keep it updated. You should poll the open orders endpoint once when you start trading to obtain the current state of any open orders.

executed_value is the cumulative match size * price and is only present for orders placed after 2016-05-20.

Get an Order

{
    "id": "68e6a28f-ae28-4788-8d4f-5ab4e5e5ae08",
    "size": "1.00000000",
    "product_id": "BTC-USD",
    "side": "buy",
    "stp": "dc",
    "funds": "9.9750623400000000",
    "specified_funds": "10.0000000000000000",
    "type": "market",
    "post_only": false,
    "created_at": "2016-12-08T20:09:05.508883Z",
    "done_at": "2016-12-08T20:09:05.527Z",
    "done_reason": "filled",
    "fill_fees": "0.0249376391550000",
    "filled_size": "0.01291771",
    "executed_value": "9.9750556620000000",
    "status": "done",
    "settled": true
}

Get a single order by order id.

HTTP Request

GET /orders/<order-id>

If the order is canceled the response may have status code 404 if the order had no matches.

Fills

List Fills

[
    {
        "trade_id": 74,
        "product_id": "BTC-USD",
        "price": "10.00",
        "size": "0.01",
        "order_id": "d50ec984-77a8-460a-b958-66f114b0de9b",
        "created_at": "2014-11-07T22:19:28.578544Z",
        "liquidity": "T",
        "fee": "0.00025",
        "settled": true,
        "side": "buy"
    }
]

Get a list of recent fills.

http request

GET /fills

Query Parameters

You can request fills for specific orders or products using query parameters.

Param Default Description
order_id all Limit list of fills to this order_id
product_id all Limit list of fills to this product_id

Settlement and Fees

Fees are recorded in two stages. Immediately after the matching engine completes a match, the fill is inserted into our datastore. Once the fill is recorded, a settlement process will settle the fill and credit both trading counterparties.

The fee field indicates the fees charged for this individual fill.

Liquidity

The liquidity field indicates if the fill was the result of a liquidity provider or liquidity taker. M indicates Maker and T indicates Taker.

Pagination

Fills are returned sorted by descending trade_id from the largest trade_id to the smallest trade_id. The CB-BEFORE header will have this first trade id so that future requests using the cb-before parameter will fetch fills with a greater trade id (newer fills).

Funding

Every order placed with a margin profile that draws funding will create a funding record.

List Fundings

[
  {
    "id": "b93d26cd-7193-4c8d-bfcc-446b2fe18f71",
    "order_id": "b93d26cd-7193-4c8d-bfcc-446b2fe18f71",
    "profile_id": "d881e5a6-58eb-47cd-b8e2-8d9f2e3ec6f6",
    "amount": "1057.6519956381537500",
    "status": "settled",
    "created_at": "2017-03-17T23:46:16.663397Z",
    "currency": "USD",
    "repaid_amount": "1057.6519956381537500",
    "default_amount": "0",
    "repaid_default": false
  },
  {
    "id": "280c0a56-f2fa-4d3b-a199-92df76fff5cd",
    "order_id": "280c0a56-f2fa-4d3b-a199-92df76fff5cd",
    "profile_id": "d881e5a6-58eb-47cd-b8e2-8d9f2e3ec6f6",
    "amount": "545.2400000000000000",
    "status": "outstanding",
    "created_at": "2017-03-18T00:34:34.270484Z",
    "currency": "USD",
    "repaid_amount": "532.7580047716682500"
  },
  {
    "id": "d6ec039a-00eb-4bec-a3e1-f5c6a97c4afc",
    "order_id": "d6ec039a-00eb-4bec-a3e1-f5c6a97c4afc",
    "profile_id": "d881e5a6-58eb-47cd-b8e2-8d9f2e3ec6f6",
    "amount": "9.9999999958500000",
    "status": "outstanding",
    "created_at": "2017-03-19T23:16:11.615181Z",
    "currency": "USD",
    "repaid_amount": "0"
  }
]

http request

GET /funding

Query Parameters

Param Options Description
status outstanding, settled, or rejected Limit list of funding records to these statuses.

Repay

Repay funding. Repays the older funding records first.

HTTP Request

POST /funding/repay

Parameters

Param Description
amount Amount of currency to repay
currency The currency, example USD

Margin Transfer

Transfer funds between your standard/default profile and a margin profile. A deposit will transfer funds from the default profile into the margin profile. A withdraw will transfer funds from the margin profile to the default profile. Withdraws will fail if they would set your margin ratio below the initial margin ratio requirement.

To get your margin profile id you can query GET /position with your margin profile’s API key.

{
  "margin_profile_id": "45fa9e3b-00ba-4631-b907-8a98cbdf21be",
  "type": "deposit",
  "currency": "USD",
  "amount": 2
}

Response

{
  "created_at": "2017-01-25T19:06:23.415126Z",
  "id": "80bc6b74-8b1f-4c60-a089-c61f9810d4ab",
  "user_id": "521c20b3d4ab09621f000011",
  "profile_id": "cda95996-ac59-45a3-a42e-30daeb061867",
  "margin_profile_id": "45fa9e3b-00ba-4631-b907-8a98cbdf21be",
  "type": "deposit",
  "amount": "2",
  "currency": "USD",
  "account_id": "23035fc7-0707-4b59-b0d2-95d0c035f8f5",
  "margin_account_id": "e1d9862c-a259-4e83-96cd-376352a9d24d",
  "margin_product_id": "BTC-USD",
  "status": "completed",
  "nonce": 25
}

http request

POST /profiles/margin-transfer

Parameters

Param Description
margin_profile_id The id of the margin profile you’d like to deposit to or withdraw from
type deposit or withdraw
currency The currency to transfer, currently on BTC or USD
amount The amount to transfer between the default and margin profile

Position

An overview of your profile.

{
  "status": "active",
  "funding": {
    "max_funding_value": "10000",
    "funding_value": "622.48199522418175",
    "oldest_outstanding": {
      "id": "280c0a56-f2fa-4d3b-a199-92df76fff5cd",
      "order_id": "280c0a56-f2fa-4d3b-a199-92df76fff5cd",
      "created_at": "2017-03-18T00:34:34.270484Z",
      "currency": "USD",
      "account_id": "202af5e9-1ac0-4888-bdf5-15599ae207e2",
      "amount": "545.2400000000000000"
    }
  },
  "accounts": {
    "USD": {
      "id": "202af5e9-1ac0-4888-bdf5-15599ae207e2",
      "balance": "0.0000000000000000",
      "hold": "0.0000000000000000",
      "funded_amount": "622.4819952241817500",
      "default_amount": "0"
    },
    "BTC": {
      "id": "1f690a52-d557-41b5-b834-e39eb10d7df0",
      "balance": "4.7051564815292853",
      "hold": "0.6000000000000000",
      "funded_amount": "0.0000000000000000",
      "default_amount": "0"
    }
  },
  "margin_call": {
    "active": true,
    "price": "175.96000000",
    "side": "sell",
    "size": "4.70515648",
    "funds": "624.04210048"
  },
  "user_id": "521c20b3d4ab09621f000011",
  "profile_id": "d881e5a6-58eb-47cd-b8e2-8d9f2e3ec6f6",
  "position": {
    "type": "long",
    "size": "0.59968368",
    "complement": "-641.91999958602800000000000000",
    "max_size": "1.49000000"
  },
  "product_id": "BTC-USD"
}

http request

GET /position

status

The status of the profile. If active, the profile can be used for trading. If pending, the profile is currently being created. If locked, the profile is undergoing a rebalance. If default, you were not able repay funding after a margin call or expired funding and now have a default.

funding [margin]

Holds details about the open/outstanding fundings taken out in the margin profile.

funding_value is the value of all outstanding fundings in USD. This value is updated every time you draw or repay funding.

max_funding_value is maximum value of fundings in USD that you can have oustanding. This value can restrict you from drawing more funding.

oldest_outstanding is the oldest funding record you have outstanding. This is important as funding can only remain outstanding for 27 days and 22 hours before being automatically closed and settled. It is recommended that you manually settle or claim the funding before it expires.

accounts

The accounts in the profile indexed by their currency.

margin call [margin]

Holds details about the resting margin call. To attempt to ensure you can repay funding we place a hidden stop like order on the book. When the last trade price hits or goes past price the margin call will trigger issuing a market order to rebalance your profile so each account has enough funds to repay all outstanding funding records.

If each account’s balance is large enough to repay the its funded_amount, active will be false signifying your profile does not have a resting margin call.

Close

HTTP Request

POST /position/close

Parameters

Param Description
repay_only either true or false

Deposits

Payment method

Request

{
    "amount": 10.00,
    "currency": "USD",
    "payment_method_id": "bc677162-d934-5f1a-968c-a496b1c1270b"
}

Response

{
    "id": "593533d2-ff31-46e0-b22e-ca754147a96a",
    "amount": "10.00",
    "currency": "USD",
    "payout_at": "2016-08-20T00:31:09Z"
}

Deposit funds from a payment method. See the Payment Methods section for retrieving your payment methods.

http request

POST /deposits/payment-method

Parameters

Param Description
amount The amount to deposit
currency The type of currency
payment_method_id ID of the payment method

Coinbase

Request

{
    "amount": 10.00,
    "currency": "BTC",
    "coinbase_account_id": "c13cd0fc-72ca-55e9-843b-b84ef628c198",
}

Response

{
    "id": "593533d2-ff31-46e0-b22e-ca754147a96a",
    "amount": "10.00",
    "currency": "BTC",
}

Deposit funds from a coinbase account. You can move funds between your Coinbase accounts and your GDAX trading accounts within your daily limits. Moving funds between Coinbase and GDAX is instant and free. See the Coinbase Accounts section for retrieving your Coinbase accounts.

http request

POST /deposits/coinbase-account

Parameters

Param Description
amount The amount to deposit
currency The type of currency
coinbase_account_id ID of the coinbase account

Withdrawals

Payment method

Request

{
    "amount": 10.00,
    "currency": "USD",
    "payment_method_id": "bc677162-d934-5f1a-968c-a496b1c1270b"
}

Response

{
    "id":"593533d2-ff31-46e0-b22e-ca754147a96a",
    "amount": "10.00",
    "currency": "USD",
    "payout_at": "2016-08-20T00:31:09Z"
}

Withdraw funds to a payment method. See the Payment Methods section for retrieving your payment methods.

http request

POST /withdrawals/payment-method

Parameters

Param Description
amount The amount to withdraw
currency The type of currency
payment_method_id ID of the payment method

Coinbase

Request

{
    "amount": 10.00,
    "currency": "BTC",
    "coinbase_account_id": "c13cd0fc-72ca-55e9-843b-b84ef628c198",
}

Response

{
    "id":"593533d2-ff31-46e0-b22e-ca754147a96a",
    "amount":"10.00",
    "currency": "BTC",
}

Withdraw funds to a coinbase account. You can move funds between your Coinbase accounts and your GDAX trading accounts within your daily limits. Moving funds between Coinbase and GDAX is instant and free. See the Coinbase Accounts section for retrieving your Coinbase accounts.

http request

POST /withdrawals/coinbase-account

Parameters

Param Description
amount The amount to withdraw
currency The type of currency
coinbase_account_id ID of the coinbase account

Crypto

Request

{
    "amount": 10.00,
    "currency": "BTC",
    "crypto_address": "0x5ad5769cd04681FeD900BCE3DDc877B50E83d469"
}

Response

{
    "id":"593533d2-ff31-46e0-b22e-ca754147a96a",
    "amount":"10.00",
    "currency": "BTC",
}

Withdraws funds to a crypto address.

http request

POST /withdrawals/crypto

Parameters

Param Description
amount The amount to withdraw
currency The type of currency
crypto_address A crypto address of the recipient

Payment Methods

List Payment Methods

[
    {
        "id": "bc6d7162-d984-5ffa-963c-a493b1c1370b",
        "type": "ach_bank_account",
        "name": "Bank of America - eBan... ********7134",
        "currency": "USD",
        "primary_buy": true,
        "primary_sell": true,
        "allow_buy": true,
        "allow_sell": true,
        "allow_deposit": true,
        "allow_withdraw": true,
        "limits": {
            "buy": [
                {
                    "period_in_days": 1,
                    "total": {
                        "amount": "10000.00",
                        "currency": "USD"
                    },
                    "remaining": {
                        "amount": "10000.00",
                        "currency": "USD"
                    }
                }
            ],
            "instant_buy": [
                {
                    "period_in_days": 7,
                    "total": {
                        "amount": "0.00",
                        "currency": "USD"
                    },
                    "remaining": {
                        "amount": "0.00",
                        "currency": "USD"
                    }
                }
            ],
            "sell": [
                {
                    "period_in_days": 1,
                    "total": {
                        "amount": "10000.00",
                        "currency": "USD"
                    },
                    "remaining": {
                        "amount": "10000.00",
                        "currency": "USD"
                    }
                }
            ],
            "deposit": [
                {
                    "period_in_days": 1,
                    "total": {
                        "amount": "10000.00",
                        "currency": "USD"
                    },
                    "remaining": {
                        "amount": "10000.00",
                        "currency": "USD"
                    }
                }
            ]
        }
    },
]

Get a list of your payment methods.

Http Request

GET /payment-methods

Coinbase Accounts

List Accounts

[
    {
        "id": "fc3a8a57-7142-542d-8436-95a3d82e1622",
        "name": "ETH Wallet",
        "balance": "0.00000000",
        "currency": "ETH",
        "type": "wallet",
        "primary": false,
        "active": true
    },
    {
        "id": "2ae3354e-f1c3-5771-8a37-6228e9d239db",
        "name": "USD Wallet",
        "balance": "0.00",
        "currency": "USD",
        "type": "fiat",
        "primary": false,
        "active": true,
        "wire_deposit_information": {
            "account_number": "0199003122",
            "routing_number": "026013356",
            "bank_name": "Metropolitan Commercial Bank",
            "bank_address": "99 Park Ave 4th Fl New York, NY 10016",
            "bank_country": {
                "code": "US",
                "name": "United States"
            },
            "account_name": "Coinbase, Inc",
            "account_address": "548 Market Street, #23008, San Francisco, CA 94104",
            "reference": "BAOCAEUX"
        }
    },
    {
        "id": "1bfad868-5223-5d3c-8a22-b5ed371e55cb",
        "name": "BTC Wallet",
        "balance": "0.00000000",
        "currency": "BTC",
        "type": "wallet",
        "primary": true,
        "active": true
    },
    {
        "id": "2a11354e-f133-5771-8a37-622be9b239db",
        "name": "EUR Wallet",
        "balance": "0.00",
        "currency": "EUR",
        "type": "fiat",
        "primary": false,
        "active": true,
        "sepa_deposit_information": {
            "iban": "EE957700771001355096",
            "swift": "LHVBEE22",
            "bank_name": "AS LHV Pank",
            "bank_address": "Tartu mnt 2, 10145 Tallinn, Estonia",
            "bank_country_name": "Estonia",
            "account_name": "Coinbase UK, Ltd.",
            "account_address": "9th Floor, 107 Cheapside, London, EC2V 6DN, United Kingdom",
            "reference": "CBAEUXOVFXOXYX"
        }
    },
]

Get a list of your coinbase accounts.

Visit the Coinbase accounts API for more information.

Http Request

GET /coinbase-accounts

Reports

Create a new report

Request

{
    "type": "fills",
    "start_date": "2014-11-01T00:00:00.000Z",
    "end_date": "2014-11-30T23:59:59.000Z"
}

Response

{
    "id": "0428b97b-bec1-429e-a94c-59232926778d",
    "type": "fills",
    "status": "pending",
    "created_at": "2015-01-06T10:34:47.000Z",
    "completed_at": undefined,
    "expires_at": "2015-01-13T10:35:47.000Z",
    "file_url": undefined,
    "params": {
        "start_date": "2014-11-01T00:00:00.000Z",
        "end_date": "2014-11-30T23:59:59.000Z"
    }
}

Reports provide batches of historic information about your account in various human and machine readable forms.

http request

POST /reports

Parameters

Param Description
type fills or account
start_date Starting date for the report (inclusive)
end_date Ending date for the report (inclusive)
product_id ID of the product to generate a fills report for. E.g. BTC-USD. Required if type is fills
account_id ID of the account to generate an account report for. Required if type is account
format pdf or csv (defualt is pdf)
email Email address to send the report to (optional)

The report will be generated when resources are available. Report status can be queried via the /reports/:report_id endpoint. The file_url field will be available once the report has successfully been created and is available for download.

Expired reports

Reports are only available for download for a few days after being created. Once a report expires, the report is no longer available for download and is deleted.

Get report status

Response (creating report)

{
    "id": "0428b97b-bec1-429e-a94c-59232926778d",
    "type": "fills",
    "status": "creating",
    "created_at": "2015-01-06T10:34:47.000Z",
    "completed_at": undefined,
    "expires_at": "2015-01-13T10:35:47.000Z",
    "file_url": undefined,
    "params": {
        "start_date": "2014-11-01T00:00:00.000Z",
        "end_date": "2014-11-30T23:59:59.000Z"
    }
}

Response (finished report)

{
    "id": "0428b97b-bec1-429e-a94c-59232926778d",
    "type": "fills",
    "status": "ready",
    "created_at": "2015-01-06T10:34:47.000Z",
    "completed_at": "2015-01-06T10:35:47.000Z",
    "expires_at": "2015-01-13T10:35:47.000Z",
    "file_url": "https://example.com/0428b97b.../fills.pdf",
    "params": {
        "start_date": "2014-11-01T00:00:00.000Z",
        "end_date": "2014-11-30T23:59:59.000Z"
    }
}

http request

GET /reports/:report_id

Once a report request has been accepted for processing, the status is available by polling the report resource endpoint.

The final report will be uploaded and available at file_url once the status indicates ready

Status

Status Description
pending The report request has been accepted and is awaiting processing
creating The report is being created
ready The report is ready for download from file_url

User Account

Trailing Volume

[
    {
        "product_id": "BTC-USD",
        "exchange_volume": "11800.00000000",
        "volume": "100.00000000",
        "recorded_at": "1973-11-29T00:05:01.123456Z"
    },
    {
        "product_id": "LTC-USD",
        "exchange_volume": "51010.04100000",
        "volume": "2010.04100000",
        "recorded_at": "1973-11-29T00:05:02.123456Z"
    }
]

http request

GET /users/self/trailing-volume

This request will return your 30-day trailing volume for all products. This is a cached value that’s calculated every day at midnight UTC.

Market Data

The Market Data API is an unauthenticated set of endpoints for retrieving market data. These endpoints provide snapshots of market data.

Products

Get Products

[
    {
        "id": "BTC-USD",
        "base_currency": "BTC",
        "quote_currency": "USD",
        "base_min_size": "0.01",
        "base_max_size": "10000.00",
        "quote_increment": "0.01"
    }
]

Get a list of available currency pairs for trading.

HTTP Request

GET /products

Details

The base_min_size and base_max_size fields define the min and max order size. The quote_increment field specifies the min order price as well as the price increment.

The order price must be a multiple of this increment (i.e. if the increment is 0.01, order prices of 0.001 or 0.021 would be rejected).

Get Product Order Book

Example Response for /products/BTC-USD/book Only the best bid and ask is returned.

{
    "sequence": "3",
    "bids": [
        [ price, size, num-orders ],
    ],
    "asks": [
        [ price, size, num-orders ],
    ]
}

Example Response for /products/BTC-USD/book?level=2

{
    "sequence": "3",
    "bids": [
        [ price, size, num-orders ],
        [ "295.96", "4.39088265", 2 ],
        ...
    ],
    "asks": [
        [ price, size, num-orders ],
        [ "295.97", "25.23542881", 12 ],
        ...
    ]
}

Example Response for /products/BTC-USD/book?level=3

{
    "sequence": "3",
    "bids": [
        [ price, size, order_id ],
        [ "295.96","0.05088265","3b0f1225-7f84-490b-a29f-0faef9de823a" ],
        ...
    ],
    "asks": [
        [ price, size, order_id ],
        [ "295.97","5.72036512","da863862-25f4-4868-ac41-005d11ab0a5f" ],
        ...
    ]
}

Get a list of open orders for a product. The amount of detail shown can be customized with the level parameter.

HTTP Request

GET /products/<product-id>/book

Details

By default, only the inside (i.e. best) bid and ask are returned. This is equivalent to a book depth of 1 level. If you would like to see a larger order book, specify the level query parameter.

If a level is not aggregated, then all of the orders at each price will be returned. Aggregated levels return only one size for each active price (as if there was only a single order for that size at the level).

Parameters

Name Default Description
level 1 Select response detail. Valid levels are documented below

Levels

Level Description
1 Only the best bid and ask
2 Top 50 bids and asks (aggregated)
3 Full order book (non aggregated)

Levels 1 and 2 are aggregated and return the number of orders at each level. Level 3 is non-aggregated and returns the entire order book.

Get Product Ticker

{
  "trade_id": 4729088,
  "price": "333.99",
  "size": "0.193",
  "bid": "333.98",
  "ask": "333.99",
  "volume": "5957.11914015",
  "time": "2015-11-14T20:46:03.511254Z"
}

Snapshot information about the last trade (tick), best bid/ask and 24h volume.

http request

GET /products/<product-id>/ticker

Real-time updates

Polling is discouraged in favor of connecting via the websocket stream and listening for match messages.

Get Trades

[{
    "time": "2014-11-07T22:19:28.578544Z",
    "trade_id": 74,
    "price": "10.00000000",
    "size": "0.01000000",
    "side": "buy"
}, {
    "time": "2014-11-07T01:08:43.642366Z",
    "trade_id": 73,
    "price": "100.00000000",
    "size": "0.01000000",
    "side": "sell"
}]

List the latest trades for a product.

http request

GET /products/<product-id>/trades

Side

The trade side indicates the maker order side. The maker order is the order that was open on the order book. buy side indicates a down-tick because the maker was a buy order and their order was removed. Conversely, sell side indicates an up-tick.

Get Historic Rates

[
    [ time, low, high, open, close, volume ],
    [ 1415398768, 0.32, 4.2, 0.35, 4.2, 12.3 ],
    ...
]

Historic rates for a product. Rates are returned in grouped buckets based on requested granularity.

http request

GET /products/<product-id>/candles

Parameters

Param Description
start Start time in ISO 8601
end End time in ISO 8601
granularity Desired timeslice in seconds

Response Items

Each bucket is an array of the following information:

  • time bucket start time
  • low lowest price during the bucket interval
  • high highest price during the bucket interval
  • open opening price (first trade) in the bucket interval
  • close closing price (last trade) in the bucket interval
  • volume volume of trading activity during the bucket interval

Get 24hr Stats

{
    "open": "34.19000000",
    "high": "95.70000000",
    "low": "7.06000000",
    "volume": "2.41000000"
}

Get 24 hr stats for the product. volume is in base currency units. open, high, low are in quote currency units.

http request

GET /products/<product-id>/stats

Currencies

Get currencies

[{
    "id": "BTC",
    "name": "Bitcoin",
    "min_size": "0.00000001"
}, {
    "id": "USD",
    "name": "United States Dollar",
    "min_size": "0.01000000"
}]

List known currencies.

http request

GET /currencies

Currency Codes

Currency codes will conform to the ISO 4217 standard where possible. Currencies which have or had no representation in ISO 4217 may use a custom code.

Code Description
BTC Bitcoin
ETH Ether
LTC Litecoin

Time

{
    "iso": "2015-01-07T23:47:25.201Z",
    "epoch": 1420674445.201
}

Get the API server time.

http request

GET /time

Epoch

The epoch field represents decimal seconds since Unix Epoch

Websocket Feed

The websocket feed provides real-time market data updates for orders and trades.

wss://ws-feed.gdax.com

Overview

Real-time market data updates provide the fastest insight into order flow and trades. This however means that you are responsible for reading the message stream and using the message relevant for your needs which can include building real-time order books or tracking real-time trades.

The websocket feed is publicly available, but connections to it are rate-limited to 1 per 4 seconds per IP.

Protocol overview

The websocket feed uses a bidirectional protocol, which encodes all messages as JSON objects. All messages have a type attribute that can be used to handle the message appropriately.

Please note that new message types can be added at any point in time. Clients are expected to ignore messages they do not support.

Error messages: Most failure cases will cause an error message (a message with the type "error") to be emitted. This can be helpful for implementing a client or debugging issues.

{
    "type": "error",
    "message": "error message",
    /* ... */
}

Subscribe

// Request
// Subscribe to ETH-USD and ETH-EUR with the level2, heartbeat and ticker channels,
// plus receive the ticker entries for ETH-BTC and ETH-GBP
{
    "type": "subscribe",
    "product_ids": [
        "ETH-USD",
        "ETH-EUR"
    ],
    "channels": [
        "level2",
        "heartbeat",
        {
            "name": "ticker",
            "product_ids": [
                "ETH-BTC",
                "ETH-GBP"
            ]
        },
    ]
}

To begin receiving feed messages, you must first send a subscribe message to the server indicating which channels and products to receive. This message is mandatory — you will be disconnected if no subscribe has been received within 5 seconds.

There are two ways to specify products ids to listen for within each channel: First, you can specify the product ids for an individual channel. Also, as a shorthand, you can define products ids at the root of the object, which will add them to all the channels you subscribe to.

// Response
{
    "type": "subscriptions",
    "channels": [
        {
            "name": "level2",
            "product_ids": [
                "ETH-USD",
                "ETH-EUR"
            ],
        },
        {
            "name": "heartbeat",
            "product_ids": [
                "ETH-USD",
                "ETH-EUR"
            ],
        },
        {
            "name": "ticker",
            "product_ids": [
                "ETH-USD",
                "ETH-EUR",
                "ETH-BTC",
                "ETH-GBP"
            ]
        },
    ]
}

Once a subscribe message is received the server will respond with a subscriptions message that lists all channels you are subscribed to.

Subsequent subscribe messages will add to the list of subscriptions. In case you already subscribed to a channel without being authenticated you will remain in the unauthenticated channel.

If you want to unsubscribe from channel/product pairs, send an unsubscribe message. The structure is equivalent to subscribe messages. As a shorthand you can also provide no product ids for a channel, which will unsubscribe you from the channel entirely.

// Request
{
    "type": "unsubscribe",
    "product_ids": [
        "ETH-USD",
        "ETH-EUR"
    ],
    "channels": ["ticker"]
}
// Request
{
    "type": "unsubscribe",
    "channels": ["heartbeat"]
}

As a response to an unsubscribe message you will receive a subscriptions message.

Authentication

It is possible to authenticate yourself when subscribing to the websocket feed.

Authentication will result in a couple of benefits:

  1. Messages where you’re one of the parties are expanded and have more useful fields
  2. You will receive private messages, such as lifecycle information about stop orders you placed
// Authenticated feed messages add user_id and
// profile_id for messages related to your user
{
    "type": "open", // "received" | "open" | "done" | "match" | "change" | "activate"
    "user_id": "5844eceecf7e803e259d0365",
    "profile_id": "765d1549-9660-4be2-97d4-fa2d65fa3352",
    /* ... */
}

Here’s an example of an authenticated subscribe request:

// Request
{
    "type": "subscribe",
    "product_ids": [
        "BTC-USD"
    ],
    "channels": ["full"],
    "signature": "...",
    "key": "...",
    "passphrase": "...",
    "timestamp": "..."
}

To authenticate, you send a subscribe message as usual, but you also pass in fields just as if you were signing a request to GET /users/self/verify. To get the necessary parameters, you would go through the same process as you do to make authenticated calls to the API.

The easiest way to connect to an authenticated feed are our gdax-node and GDAX trading toolkit libraries.

Sequence Numbers

Most feed messages contain a sequence number. Sequence numbers are increasing integer values for each product with every new message being exactly 1 sequence number than the one before it.

If you see a sequence number that is more than one value from the previous, it means a message has been dropped. A sequence number less than one you have seen can be ignored or has arrived out-of-order. In both situations you may need to perform logic to make sure your system is in the correct state.

Channels

The heartbeat channel

// Request
{
    "type": "subscribe",
    "channels": [{ "name": "heartbeat", "product_ids": ["ETH-EUR"] }]
}

To receive heartbeat messages for specific products once a second subscribe to the heartbeat channel. Heartbeats also include sequence numbers and last trade ids that can be used to verify no messages were missed.

// Heartbeat message
{
    "type": "heartbeat",
    "sequence": 90,
    "last_trade_id": 20,
    "product_id": "BTC-USD",
    "time": "2014-11-07T08:19:28.464459Z"
}

The ticker channel

The ticker channel provides real-time price updates every time a match happens. It batches updates in case of cascading matches, greatly reducing bandwidth requirements.

{
    "type": "ticker",
    "trade_id": 20153558,
    "sequence": 3262786978,
    "time": "2017-09-02T17:05:49.250000Z",
    "product_id": "BTC-USD",
    "price": "4388.01000000",
    "side": "buy", // Taker side
    "last_size": "0.03000000",
    "best_bid": "4388",
    "best_ask": "4388.01"
}

Please note that more information will be added to messages from this channel in the near future.

The level2 channel

The easiest way to keep a snapshot of the order book is to use the level2 channel. It guarantees delivery of all updates, which reduce a lot of the overhead required when consuming the full channel.

{
    "type": "snapshot",
    "product_id": "BTC-EUR",
    "bids": [["1", "2"]],
    "asks": [["2", "3"]],
}

When subscribing to the channel it will send a message with the type snapshot and the corresponding product_id. bids and asks are arrays of [price, size] tuples and represent the entire order book.

{
    "type": "l2update",
    "product_id": "BTC-EUR",
    "changes": [
        ["buy", "1", "3"],
        ["sell", "3", "1"],
        ["sell", "2", "2"],
        ["sell", "4", "0"]
    ]
}

Subsequent updates will have the type l2update. The changes property of l2updates is an array with [side, price, size] tuples. Please note that size is the updated size at that price level, not a delta. A size of "0" indicates the price level can be removed.

Updates are provided for the buy and sell sides individually. When a price level switches sides, expect to see an update with size "0" for the old side and an update with the new size on the new side.

The user channel

This channel is a version of the full channel that only contains messages that include the authenticated user. Consequently, you need to be authenticated to receive any messages.

The matches channel

If you are only interested in match messages you can subscribe to the matches channel. This is useful when you’re consuming the remaining feed using the level 2 channel.

Please note that messages can be dropped from this channel. By using the heartbeat channel you can track the last trade id and fetch trades that you missed from the REST API.

The full channel

The full channel provides real-time updates on orders and trades. These updates can be applied on to a level 3 order book snapshot to maintain an accurate and up-to-date copy of the exchange order book.

An algorithm to maintain an up-to-date level 3 order book is described below. Please note that you will rarely need to implement this yourself.

  1. Send a subscribe message for the product(s) of interest and the full channel.
  2. Queue any messages received over the websocket stream.
  3. Make a REST request for the order book snapshot from the REST feed.
  4. Playback queued messages, discarding sequence numbers before or equal to the snapshot sequence number.
  5. Apply playback messages to the snapshot as needed (see below).
  6. After playback is complete, apply real-time stream messages as they arrive.

The following messages are sent over the websocket stream in JSON format when subscribing to the full channel:

Received

{
    "type": "received",
    "time": "2014-11-07T08:19:27.028459Z",
    "product_id": "BTC-USD",
    "sequence": 10,
    "order_id": "d50ec984-77a8-460a-b958-66f114b0de9b",
    "size": "1.34",
    "price": "502.1",
    "side": "buy",
    "order_type": "limit"
}
{
    "type": "received",
    "time": "2014-11-09T08:19:27.028459Z",
    "product_id": "BTC-USD",
    "sequence": 12,
    "order_id": "dddec984-77a8-460a-b958-66f114b0de9b",
    "funds": "3000.234",
    "side": "buy",
    "order_type": "market"
}

A valid order has been received and is now active. This message is emitted for every single valid order as soon as the matching engine receives it whether it fills immediately or not.

The received message does not indicate a resting order on the order book. It simply indicates a new incoming order which as been accepted by the matching engine for processing. Received orders may cause match message to follow if they are able to begin being filled (taker behavior). Self-trade prevention may also trigger change messages to follow if the order size needs to be adjusted. Orders which are not fully filled or canceled due to self-trade prevention result in an open message and become resting orders on the order book.

Market orders (indicated by the order_type field) may have an optional funds field which indicates how much quote currency will be used to buy or sell. For example, a funds field of 100.00 for the BTC-USD product would indicate a purchase of up to 100.00 USD worth of bitcoin.

Open

{
    "type": "open",
    "time": "2014-11-07T08:19:27.028459Z",
    "product_id": "BTC-USD",
    "sequence": 10,
    "order_id": "d50ec984-77a8-460a-b958-66f114b0de9b",
    "price": "200.2",
    "remaining_size": "1.00",
    "side": "sell"
}

The order is now open on the order book. This message will only be sent for orders which are not fully filled immediately. remaining_size will indicate how much of the order is unfilled and going on the book.

Done

{
    "type": "done",
    "time": "2014-11-07T08:19:27.028459Z",
    "product_id": "BTC-USD",
    "sequence": 10,
    "price": "200.2",
    "order_id": "d50ec984-77a8-460a-b958-66f114b0de9b",
    "reason": "filled", // or "canceled"
    "side": "sell",
    "remaining_size": "0"
}

The order is no longer on the order book. Sent for all orders for which there was a received message. This message can result from an order being canceled or filled. There will be no more messages for this order_id after a done message. remaining_size indicates how much of the order went unfilled; this will be 0 for filled orders.

market orders will not have a remaining_size or price field as they are never on the open order book at a given price.

Match

{
    "type": "match",
    "trade_id": 10,
    "sequence": 50,
    "maker_order_id": "ac928c66-ca53-498f-9c13-a110027a60e8",
    "taker_order_id": "132fb6ae-456b-4654-b4e0-d681ac05cea1",
    "time": "2014-11-07T08:19:27.028459Z",
    "product_id": "BTC-USD",
    "size": "5.23512",
    "price": "400.23",
    "side": "sell"
}

A trade occurred between two orders. The aggressor or taker order is the one executing immediately after being received and the maker order is a resting order on the book. The side field indicates the maker order side. If the side is sell this indicates the maker was a sell order and the match is considered an up-tick. A buy side match is a down-tick.

If authenticated, and you were the taker, the message would also have the following fields:

taker_user_id: "5844eceecf7e803e259d0365",
user_id: "5844eceecf7e803e259d0365",
taker_profile_id: "765d1549-9660-4be2-97d4-fa2d65fa3352",
profile_id: "765d1549-9660-4be2-97d4-fa2d65fa3352"

Change

{
    "type": "change",
    "time": "2014-11-07T08:19:27.028459Z",
    "sequence": 80,
    "order_id": "ac928c66-ca53-498f-9c13-a110027a60e8",
    "product_id": "BTC-USD",
    "new_size": "5.23512",
    "old_size": "12.234412",
    "price": "400.23",
    "side": "sell"
}
{
    "type": "change",
    "time": "2014-11-07T08:19:27.028459Z",
    "sequence": 80,
    "order_id": "ac928c66-ca53-498f-9c13-a110027a60e8",
    "product_id": "BTC-USD",
    "new_funds": "5.23512",
    "old_funds": "12.234412",
    "price": "400.23",
    "side": "sell"
}

An order has changed. This is the result of self-trade prevention adjusting the order size or available funds. Orders can only decrease in size or funds. change messages are sent anytime an order changes in size; this includes resting orders (open) as well as received but not yet open. change messages are also sent when a new market order goes through self trade prevention and the funds for the market order have changed.

Margin Profile Update

This feed message will only be received if you are authenticated with a margin profile.

{
  "type": "margin_profile_update",
  "product_id": "BTC-USD",
  "timestamp": "2017-03-13T20:58:59.071Z",
  "user_id": "4fee694c4ddbe2000300017e",
  "profile_id": "df46176d-798e-40be-819c-c94b1cbf97a7",
  "nonce": 4,
  "position": "long",
  "position_size": "16.65808012",
  "position_compliment": "-21049.99999776145250000000000000",
  "position_max_size": "16.65808012",
  "call_side": "sell",
  "call_price": "750.39",
  "call_size": "16.65808012",
  "call_funds": "10025.06265440",
  "covered": false,
  "next_expire_time": "2017-04-10T18:58:59.070Z",
  "base_balance": "16.65808012",
  "base_funding": "0",
  "quote_balance": "0.00000223457250000000000000",
  "quote_funding": "9999.9999999960250000",
  "private": true
}

Activate

An activate message is sent when a stop order is placed. When the stop is triggered the order will be placed and go through the order lifecycle.

{
  "type": "activate",
  "product_id": "test-product",
  "timestamp": "1483736448.299000",
  "user_id": "12",
  "profile_id": "30000727-d308-cf50-7b1c-c06deb1934fc",
  "order_id": "7b52009b-64fd-0a2a-49e6-d8a939753077",
  "stop_type": "entry",
  "side": "buy",
  "stop_price": "80",
  "size": "2",
  "funds": "50",
  "taker_fee_rate": "0.0025",
  "private": true,
}

FIX API

FIX (Financial Information eXchange) is a standard protocol which can be used to enter orders, submit cancel requests, and receive fills. Users of the FIX API will typically have existing software using FIX for order management. Users who are not familiar with FIX should first consider using the REST API.

FIX API Endpoint URL

tcp+ssl://fix.gdax.com:4198

Connectivity

Before logging onto a FIX session, clients must establish a secure connection to the FIX gateway (fix.gdax.com:4198). If your FIX implementation does not support establishing a TCP SSL connection natively, you will need to setup a local proxy such as stunnel to establish a secure connection to the FIX gateway. See the SSL Tunnels section for more details and examples.

Messages

The baseline specification for this API is FIX 4.2. There are additional tags from later versions of FIX, and custom tags in the high number range as allowed by the standard.

A standard header must be present at the start of every message in both directions.

Tag Name Description
8 BeginString Must be FIX.4.2
49 SenderCompID Client API key (on messages from the client)
56 TargetCompID Must be Coinbase (on messages from the client)

Logon (A)

// create a new Logon message
var logon = new Msgs.Logon();
logon.SendingTime = new Date();
logon.HeartBtInt = 30;
logon.EncryptMethod = 0;
logon.passphrase = '...';

var presign = [
    logon.SendingTime,
    logon.MsgType,
    session.outgoing_seq_num,
    session.sender_comp_id,
    session.target_comp_id,
    passphrase
].join('\x01');

// add the presign string to the RawData field of the Logon message
logon.RawData = sign(presign, secret);

// send the logon message to the server
session.send(logon);

function sign(what, secret) {
    var key = Buffer(secret, 'base64');
    var hmac = crypto.createHmac('sha256', key);
    return hmac.update(what).digest('base64');
}

Sent by the client to initiate a session, and by the server as an acknowledgement. Only one session may exist per connection; sending a Logon message within an established session is an error.

Tag Name Description
98 EncryptMethod Must be 0 (None)
108 HeartBtInt Must be 30 (seconds)
554 Password Client API passphrase
96 RawData Client message signature (see below)
8013 CancelOrdersOnDisconnect If set to Y, cancel all open orders for the current profile on disconnect

The Logon message sent by the client must be signed for security. The signing method is described in Signing a Message. The prehash string is the following fields joined by the FIX field separator (ASCII code 1):

SendingTime, MsgType, MsgSeqNum, SenderCompID, TargetCompID, Password.

There is no trailing separator. The RawData field should be a base64 encoding of the HMAC signature.

Logout (5)

Sent by either side to initiate session termination. The side which receives this message first should reply with the same message type to confirm session termination. Closing a connection without logging out of the session first is an error.

New Order Single (D)

Sent by the client to enter an order.

Tag Name Description
21 HandlInst Must be 1 (Automated)
11 ClOrdID UUID selected by client to identify the order
55 Symbol E.g. BTC-USD
54 Side Must be 1 to buy or 2 to sell
44 Price Limit price (e.g. in USD) (Limit order only)
38 OrderQty Order size in base units (e.g. BTC)
152 CashOrderQty Order size in quote units (e.g. USD) (Market order only)
40 OrdType Must be 1 for Market, 2 for Limit or 3 for Stop Market
99 StopPx Stop price for order. (Stop Market order only)
59 TimeInForce Must be a valid TimeInForce value. See the table below (Limit order only)
7928 SelfTradePrevention Optional, see the table below

SelfTradePrevention Values

Value Description
D Decrement and cancel (the default)
O Cancel resting order
N Cancel incoming order
B Cancel both orders

If an order is decremented due to self-trade prevention, an Execution Report will be sent to the client with ExecType=D indicating unsolicited OrderQty reduction (i.e. partial cancel).

See the self-trade prevention documentation for more details about this field.

TimeInForce Values

Value Description
1 Good Till Cancel
3 Immediate or Cancel
4 Fill or Kill
P Post-Only

The post-only flag (P) indicates that the order should only make liquidity. If any part of the order results in taking liquidity, the order will be rejected and no part of it will execute. Open Post-Only orders will be treated as Good Till Cancel.

See the time in force documentation for more details about these values.

Errors

If a trading error occurs (e.g. user has insufficient funds), an ExecutionReport with ExecType=8 is sent back, signifying that the order was rejected.

Order Cancel Request (F)

Sent by the client to cancel an order.

Tag Name Description
11 ClOrdID UUID selected by client for the order
37 OrderID OrderID from the ExecutionReport with OrdStatus=New (39=0)
41 OrigClOrdID ClOrdID of the order to cancel (originally assigned by the client)
55 Symbol Symbol of the order to cancel (must match Symbol of the Order)

ClOrdID

Use of the ClOrdID is not available after reconnecting or starting a new session. You should use the OrderID obtained via the ExecutionReport once available.

Order Status Request (H)

Sent by the client to obtain information about pending orders.

Tag Name Description
37 OrderID OrderID of order(s) to be sent back. Can be equal to * (wildcard) to send back all pending orders

Response

The response to an Order Status Request is a series of ExecutionReports with ExecType=I, each representing one open order belonging to the user. If the user has no open orders, a single ExecutionReport is sent back with OrderID=0.

Execution Report (8)

Sent by the server when an order is accepted, rejected, filled, or canceled. Also sent when the user sends an OrderStatusRequest.

Tag Name Description
11 ClOrdID Only present on order acknowledgements, ExecType=New (150=0)
37 OrderID OrderID from the ExecutionReport with ExecType=New (39=0)
55 Symbol Symbol of the original order
54 Side Must be 1 to buy or 2 to sell
32 LastShares Amount filled (if ExecType=1). Also called LastQty as of FIX 4.3
44 Price Price of the fill if ExecType indicates a fill, otherwise the order price
38 OrderQty OrderQty as accepted (may be less than requested upon self-trade prevention)
60 TransactTime Time the event occurred
150 ExecType May be 1 (Partial fill) for fills, D for self-trade prevention, etc.
136 NoMiscFees 1 (Order Status Request response only)
137 MiscFeeAmt Fee (Order Status Request response only)
139 MiscFeeType 4 (Exchange fees) (Order Status Request response only)

ExecType Values

ExecType Description
0 New Order
1 Fill
3 Done
4 Canceled
7 Stopped
8 Rejected
D Order Changed
I Order Status

Order Cancel Reject (9)

Sent by the server when an Order Cancel Request cannot be satisfied, e.g. because the order is already canceled or completely filled.

Tag Name Description
11 ClOrdID As on the cancel request
37 OrderID As on the cancel request
41 OrigClOrdID As on the cancel request
39 OrdStatus 4 if too late to cancel
434 CxlRejResponseTo 1 (Order Cancel Request)

Reject (3)

Sent by either side upon receipt of a message which cannot be processed, e.g. due to missing fields or an unsupported message type.

Tag Name Description
45 RefSeqNum MsgSeqNum of the rejected incoming message
371 RefTagID Tag number of the field which caused the reject (optional)
372 RefMsgType MsgType of the rejected incoming message
58 Text Human-readable description of the error (optional)
373 SessionRejectReason Code to identify reason for reject

SessionRejectReason Values

The following values can be sent by the server.

Value Description
1 Required tag missing
5 Value is incorrect (out of range) for this tag
6 Incorrect data format for value
11 Invalid MsgType (35)

Heartbeat (0)

Sent by both sides if no messages have been sent for HeartBtInt seconds as agreed during logon. May also be sent in response to a Test Request.

Tag Name Description
112 TestReqID Copied from the Test Request, if any

Test Request (1)

May be sent at any time by either side.

Tag Name Description
112 TestReqID Free text

SSL Tunnels

fix.gdax.com:4198 only accepts TCP connections secured by SSL. If your FIX client library cannot establish an SSL connection natively, you will need to run a local proxy that will establish a secure connection and allow unencrypted local connections.

Stunnel Configuration

This is an example configuration file for stunnel to listen on a port locally and proxy unencrypted TCP connections to the encrypted SSL connection. The service name (Coinbase) and the accept port (4197) may be changed to any suitable values.

[Coinbase]
client = yes
accept = 4197
connect = fix.gdax.com:4198
verify = 4
CAfile = /example/path/to/fix.gdax.com.pem

When stunnel is started with the above configuration file, it will run in the background. On Unix-like systems the option foreground = yes may be specified at the top of the file to avoid running in the background. For testing it may be easier to use foreground mode, or to specify the top-level output option as a file path where stunnel will write log messages.

If your system has OpenSSL installed, you can run this command to download the certificate:

openssl s_client -showcerts -connect fix.gdax.com:4198 < /dev/null | openssl x509 -outform PEM > fix.gdax.com.pem