Introduction

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.

Upcoming Changes

General

Matching Engine

Coinbase Pro 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 Coinbase Pro. 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

Coinbase Pro 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). Maker and taker fees are calculated hourly based on the user’s 30d USD-equivalent trading volume:

User 30 day USD volume

Taker fee

Maker fee

$0 - $10m

0.30 %

0 %

$10m - $100m

0.20 %

0 %

$100m+

0.10 %

0 %

HOW TAKER FEES ARE CALCULATED

Your taker fee is based upon total USD trading volume across all Order Books over the trailing 30 day period. For example, a purchase of 1 BTC for $10,000 on the BTC-USD book will count as $10,000 towards your 30 day USD volume.

HOW VOLUMES ARE CALCULATED ON NON-USD BOOKS

Transactions made on non-USD books are converted to USD based on the most recent fill price on the corresponding USD book. For example, a purchase of 1 ETH for 0.1 BTC on the ETH-BTC book will count as the most recent fill price of 1 ETH on the ETH-USD Order Book.

Deposit/Withdraw Fees

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

Data Centers

Coinbase Pro data centers are in the Amazon US East N. Virginia (us-east-1) region.

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.

API

REST API Endpoint URL

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

Coinbase Pro 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.

Cursor pagination can be unintuitive at first. before and after cursor arguments should not be confused with before and after in chronological time. Most paginated requests return the latest information (newest) as the first page sorted by newest (in chronological time) first. To get older information you would request pages after the initial page. To get information newer, you would request pages before the first page.

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 the number of incoming messages to 50 commands per second.

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 Coinbase Pro website. 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 Coinbase Pro; the Passphrase will be provided by you to further secure your API access. Coinbase Pro stores the salted hash of your passphrase for verification, but cannot recover the passphrase if you forget it.

API Key Permissions

You can restrict the functionality of API keys. Before creating the key, you must choose what permissions you would like the key to have. The permissions are:

View - Allows a key read permissions. This includes all GET endpoints.

Transfer - Allows a key to transfer currency on behalf of an account, including deposits and withdraws. Enable with caution - API key transfers WILL BYPASS two-factor authentication.

Trade - Allows a key to enter orders, as well as retrieve trade data. This includes POST /orders and several GET endpoints.

Please refer to documentation below to see what API key permissions are required for a specific route.

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

varcrypto=require('crypto');varsecret='PYPd1Hv4J6/7x...';vartimestamp=Date.now()/1000;varrequestPath='/orders';varbody=JSON.stringify({price:'1.0',size:'1.0',side:'buy',product_id:'BTC-USD'});varmethod='POST';// create the prehash string by concatenating required partsvarwhat=timestamp+method+requestPath+body;// decode the base64 secretvarkey=Buffer(secret,'base64');// create a sha256 hmac with the secretvarhmac=crypto.createHmac('sha256',key);// sign the require message with the hmac// and finally base64 encode the resultreturnhmac.update(what).digest('base64');

require'base64'require'openssl'require'json'classCoinbaseExchangedefinitialize(key,secret,passphrase)@key=key@secret=secret@passphrase=passphraseenddefsignature(request_path='',body='',timestamp=nil,method='GET')body=body.to_jsonifbody.is_a?(Hash)timestamp=Time.now.to_iif!timestampwhat="#{timestamp}#{method}#{request_path}#{body}";# create a sha256 hmac with the secretsecret=Base64.decode64(@secret)hash=OpenSSL::HMAC.digest('sha256',secret,what)Base64.strict_encode64(hash)endend

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.

Remember to first base64-decode the alphanumeric secret string (resulting in 64 bytes) before using it as the key for HMAC. Also, base64-encode the digest output before sending in the header.

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.

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.

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

API Key Permissions

This endpoint requires either the “view” or “trade” permission.

This request is paginated

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.

You can place two types of orders: limit and market.
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

API Key Permissions

This endpoint requires the “trade” permission.

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 or market (default is limit)

side

buy or sell

product_id

A valid product id

stp

[optional] Self-trade prevention flag

stop

[optional] Either loss or entry. Requires stop_price to be defined.

stop_price

[optional] Only if stop is defined. Sets trigger price for stop order.

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.

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

Stop orders become active and wait to trigger based on the movement of the last trade price.
There are two types of stop orders, stop loss and stop entry:

stop: 'loss': Triggers when the last trade price changes to a value at or below the stop_price.

stop: 'entry': Triggers when the last trade price changes to a value at or above the stop_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 either market or limit orders, depending on the type.
They are therefore subject to 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 Coinbase Pro 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 limitbuy 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 marketbuy 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 Coinbase Pro. 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.

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.

Open orders do not expire and will remain open until they are either filled or canceled.

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>

API Key Permissions

This endpoint requires the “trade” permission.

The order id is the server-assigned order id and not the optional client_oid.

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.

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.

Open orders may change state between the request and the response depending on market conditions.

HTTP request

API Key Permissions

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

DEPRECATION NOTICE - Requests without either order_id or product_id will be rejected after 8/23/18.

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

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

HTTP request

POST /reports

API Key Permissions

This endpoint requires either the “view” or “trade” permission.

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 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. The size field is the sum of the size of the orders at that price, and num-orders is the count of orders at that price; size should not be multiplied by num-orders.

Level 3 is non-aggregated and returns the entire order book.

This request is NOT paginated. The entire book is returned in one response.

Level 1 and Level 2 are recommended for polling. For the most up-to-date data, consider using the websocket stream.

Level 3 is only recommended for users wishing to maintain a full real-time order book using the websocket stream. Abuse of Level 3 via polling will cause your access to be limited or blocked.

HTTP request

GET /products/<product-id>/trades

This request is paginated.

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

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

Historical rate data may be incomplete. No data is published for intervals where there are no ticks.

Historical rates should not be polled frequently. If you need real-time information, use the trade and book endpoints along with the websocket feed.

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

Details

If either one of the start or end fields are not provided then both fields will be ignored. If a custom time range is not declared then one ending now is selected.

The granularity field must be one of the following values: {60, 300, 900, 3600, 21600, 86400}. Otherwise, your request will be rejected. These values correspond to timeslices representing one minute, five minutes, fifteen minutes, one hour, six hours, and one day, respectively.

If data points are readily available, your response may contain as many as 300 candles and some of those candles may precede your declared start value.

The maximum number of data points for a single request is 300 candles. If your selection of start/end time and granularity will result in more than 300 data points, your request will be rejected. If you wish to retrieve fine granularity data over a larger time range, you will need to make multiple requests with new start/end ranges.

HTTP request

Epoch

Websocket Feed

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.

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.

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.

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.

Authenticated feed messages do not increment the sequence number.
It is currently not possible to detect if an authenticated feed message was dropped.

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.

While a websocket connection is over TCP, the websocket servers receive market data in a manner which can result in dropped messages.
Your feed consumer should either be designed to expect and handle sequence gaps and out-of-order messages, or use channels that guarantee delivery of messages.

If you want to keep an order book in sync, consider using the level 2 channel, which provides such guarantees.

Channels

The heartbeat channel

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.

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.

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.

Note: If you are maintaining a level 2 order book, please consider switching to the level 2 channel.

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.

Send a subscribe message for the product(s) of interest and the full channel.

After playback is complete, apply real-time stream messages as they arrive.

All open and match messages will always result in a change to the order book.
Not all done or change messages will result in changing the order book.
These messages will be sent for received orders which are not yet on the order book.
Do not alter the order book for such messages, otherwise your order book will be incorrect.

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

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

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.

There will be no open message for orders which will be filled immediately.
There will be no open message for market orders since they are filled immediately.

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.

A done message will be sent for received orders which are fully filled or canceled due to self-trade prevention.
There will be no open message for such orders.
done messages for orders which are not on the book should be ignored when maintaining a real-time order book.

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:

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.

change messages for received but not yet open orders can be ignored when building a real-time order book.
The side field of a change message and price can be used as indicators for whether the change message is relevant if building from a level 2 book.

Any change message where the price is null indicates that the change message is for a market order.
Change messages for limit orders will always have a price specified.

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.

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.pro.coinbase.com:4198

Resend requests are not supported. Every connection establishes a new session and a new set of session sequence numbers.

Connectivity

Before logging onto a FIX session, clients must establish a secure connection to the FIX gateway (fix.pro.coinbase.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.

Coinbase Pro does not support static IP addresses. If your firewall rules require a static IP address, you will need to create a TCP proxy server with a static IP address which is capable of resolving an IP address using DNS.

If connecting from servers outside of AWS which require firewall rules, please use the AWS provided resources to determine how best to whitelist AWS IP ranges.

Routine disconnects occur every Monday at 1 PM Pacific Time. At that time, a Logout message will be sent from the server to indicate the session is ending.

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 messagevarlogon=newMsgs.Logon();logon.SendingTime=newDate();logon.HeartBtInt=30;logon.EncryptMethod=0;logon.passphrase='...';varpresign=[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 messagelogon.RawData=sign(presign,secret);// send the logon message to the serversession.send(logon);functionsign(what,secret){varkey=Buffer(secret,'base64');varhmac=crypto.createHmac('sha256',key);returnhmac.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

Y: Cancel all open orders for the current profile; S: Cancel open orders placed during session

9406

DropCopyFlag

If set to Y, execution reports will be generated for all user orders (defaults to Y)

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

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

A single API key must not be used in multiple connections at the same time. To establish multiple FIX connections, please generate a new API key for each one. A maximum of 10 connections can be established.

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, 3 for Stop Market, or 4 for Stop Limit

99

StopPx

Stop price for order

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

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 (150=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)

152

CashOrderQty

Order size in quote units (e.g. USD) (Market order only)

60

TransactTime

Time the event occurred

150

ExecType

May be 1 (Partial fill) for fills, D for self-trade prevention, etc.

39

OrdStatus

Order status as of the current message

103

OrdRejReason

Insufficient funds=3, Post-only=8, Unknown error=0

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)

1003

TradeID

Product unique trade id

1057

AggressorIndicator

Y for taker orders, N for maker orders

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

102

CxlRejReason

1 if the order is unknown

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.pro.coinbase.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.

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.

The stunnel configuration must include either verify=3 or verify=4 to enable client certificate pinning. The exchange certificate is available via pro.coinbase.com and must be installed in a secure (not openly writable) directory on the client system which is specified in the stunnel configuration file as CAfile.

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