Crypto starts with Bitvavo. You use Bitvavo API to buy, sell and store over 300 digital assets on Bitvavo from inside your app. Want to try out the APIs before you start developing your app?
You access Bitvavo SDK using REST or WebSocket. The Base URLs are:
https://api.bitvavo.com/v2/
wss://ws.bitvavo.com/v2/
Both protocols return JSON encoded responses, and use standard HTTP status codes. All calls to Bitvavo related to trading, transfer or your account must be authenticated. Bitvavo Rate limits ensure the best performance and stability.
To make your first calls to Bitvavo:
Setup your development environment
To access Bitvavo API, either:
Copy your Bitvavo authentication information locally
Download your API key and secret from Bitvavo Dashboard to a secure location.
Retrieve Market data or Synchronize with Bitvavo
Use these unauthenticated endpoints to retrieve the information you need to trade. For example, to retrieve the open, high, low, close, volume and volumeQuote for each market for the last 24 hours, call:
curl --location 'https://api.bitvavo.com/v2/ticker/24h'
The returned JSON object looks like:
[
{
"market": "1INCH-EUR",
"startTimestamp": 1704276900209,
"timestamp": 1704363300209,
"open": "0.44323",
"openTimestamp": 1704277090309,
"high": "0.44454",
"low": "0.33101",
"last": "0.43167",
"closeTimestamp": 1704363292923,
"bid": "0.42915",
"bidSize": "1161.3",
"ask": "0.43215",
"askSize": "1152.4",
"volume": "717262.96917523",
"volumeQuote": "290421.5350422048742"
},
{
"market": "AAVE-EUR",
// ...
},
// ...
]
Trade on Bitvavo, transfer funds or update your account
Use these highly secure endpoints to handle all aspects of your financial interactions with Bitvavo. For example, to place an order, sign the following REST request and run:
curl --location 'https://api.bitvavo.com/v2/order' \
--header 'Bitvavo-Access-Key: <replace with your access key>' \
--header 'Bitvavo-Access-Signature: <A SHA256 HMAC hex digest of timestamp + method + url + body>' \
--header 'Bitvavo-Access-Timestamp: <Current timestamp in milliseconds>' \
--header 'Bitvavo-Access-Window: 10000' \
--header 'Content-Type: application/json' \
--data '{
"market": "BTC-EUR",
"side": "buy",
"orderType": "market",
"amount": "10",
"responseRequired": true
}'
The returned JSON object looks like:
{
"orderId": "1be6d0df-d5dc-4b53-a250-jamesbondis007",
"market": "BTC-EUR",
"created": 1542621155181,
"updated": 1542621155181,
"status": "new",
"side": "buy",
"orderType": "limit",
"amount": "10",
"amountRemaining": "9.995",
"price": "7000",
"amountQuote": "5000",
"amountQuoteRemaining": "5000",
"onHold": "9109.61",
"onHoldCurrency": "BTC",
"filledAmount": "0",
"filledAmountQuote": "0",
"feePaid": "0",
"feeCurrency": "EUR",
"fills": [
{
"id": "371c6bd3-d06d-4573-9f15-spectre",
"timestamp": 1542967486256,
"amount": "0.005",
"price": "5000.1",
"taker": true,
"fee": "0.03",
"feeCurrency": "EUR",
"settled": true
}
],
"selfTradePrevention": "decrementAndCancel",
"visible": true,
"timeInForce": "GTC",
"postOnly": true,
"disableMarketProtection": true
}
And that is all, you are ready to trade on Bitvavo using the API.
The structure of Bitvavo API is:
Unauthenticated endpoints: return public information about markets and trades on Bitvavo.
You can make calls to these endpoints without your API key and secret. However, unauthenticated calls have lower rate limits based on your IP address, and your account is blocked for longer if you exceed your limit.
Authenticated endpoints: these private endpoints enable account-specific interactions, such as placing and managing orders, viewing your account history, or withdrawing assets.
For these calls to succeed you must create your API key and secret and make Authenticated calls.
Subscription WebSocket: securely subscribe to these channels and retrieve the latest information about markets, your trades and your account in your WebSocket callback.
Bitvavo is hosted in the Amazon Frankfurt region.
You control the actions your app can execute using the permissions you assign to an
API key. Each key consists of an API key name and a
corresponding API secret.
Possible permissions are:
Read-only: retrieve information from Transfer endpoints and
Account endpoints. GET your account balance and the trading fees you have
incurred. Also the history of deposits to and withdrawals from your account.
Trade digital assets: place, update, view and cancel orders using the Trading endpoints. Check your open orders, view your order and trade history. To obtain order and trade information, your API key must also have the Read-only permission.
Withdraw digital assets: withdraw your assets to an external cryptocurrency address or verified bank account.
Best practice is to NOT grant this privilege. Withdrawals made using Bitvavo API do not require 2FA and e-mail confirmation.
You create API keys in Bitvavo Dashboard. When you create an API key, you must download the API secret to a secure location immediately, you cannot retrieve it later. Best practice is to limit access each API key to a few whitelisted IP addresses.
To make an authenticated connection with Bitvavo, you send the following HTTP headers in every call to Bitvavo API:
HTTP Header | Description | Required |
---|---|---|
Bitvavo-Access-Key |
An API Key with the authentication permissions required for the trading workflow you are implementing. | ✓ |
Bitvavo-Access-Timestamp |
A unix-timestamp in milliseconds showing the time you make this call to Bitvavo. | ✓ |
Bitvavo-Access-Signature |
A SHA256 HMAC hex digest of:
|
✓ |
Bitvavo-Access-Window |
The execution timeout in milliseconds after Bitvavo-Access-Timestamp . The
default value is 10000 , the maximum value is 60000 . That is, 10 seconds and
60 seconds respectively. |
✘ |
For Bitvavo-Access-Signature
, the SHA256 HMAC hex digest of the following values:
bitvavo
1548172481125
POST
/v2/order
{"market":"BTC-EUR","side":"buy","price":"5000","amount":"1.23","orderType":"limit"}
is 44d022723a20973a18f7ee97398b9fdd405d2d019c8d39e24b8cc0dcb39ca016
.
The following Python code sample shows how to sign a request for a call to the authenticate action:
import hashlib
import hmac
import json
import websocket
import time
class BitvavoWebSocketClient:
"""
A class to interact with the Bitvavo WebSocket API.
"""
def __init__(self, api_key: str, api_secret: str, access_window: int = 10000):
self.api_key = api_key
self.api_secret = api_secret
self.access_window = access_window
self.endpoint = 'wss://ws.bitvavo.com/v2/'
self.request_id = 0
self.ws = None
def authenticate(self):
"""
Send an instruction to Bitvavo to authenticate your connection.
"""
timestamp = int(time.time() * 1000)
body = {
'key': self.api_key,
'signature': self.create_signature(timestamp),
'timestamp': timestamp,
'window': self.access_window,
}
self.call_action(action='authenticate', body=body)
def create_signature(self, timestamp: int):
"""
Create a hashed code to authenticate your connection to Bitvavo API.
"""
string = str(timestamp) + 'GET' + '/v2/websocket'
signature = hmac.new(self.api_secret.encode('utf-8'), string.encode('utf-8'), hashlib.sha256).hexdigest()
return signature
def call_action(self, action: str, body: dict):
"""
Send an instruction to Bitvavo to perform an action.
:param action: the action to perform. For example, `authenticate`.
:param body: the parameters for the call. For example, {'key': 'your_api_key', 'signature': 'your_signature'}.
"""
request_id = self.request_id
self.request_id += 1
body['action'] = action
body['requestId'] = request_id
self.send_message(body)
def send_message(self, message: dict):
"""
Send a message to Bitvavo API.
"""
if self.ws is None:
self.ws = websocket.create_connection(self.endpoint)
self.ws.send(json.dumps(message))
The following Python code sample shows how to sign a request for a call to the POST /order endpoint:
import hashlib
import hmac
import json
import requests
import time
class BitvavoRestClient:
"""
A class to interact with the Bitvavo REST API.
"""
def __init__(self, api_key: str, api_secret: str, access_window: int = 10000):
self.api_key = api_key
self.api_secret = api_secret
self.access_window = access_window
self.base = 'https://api.bitvavo.com/v2'
def place_order(self, market: str, side: str, order_type: str, body: dict):
"""
Send an instruction to Bitvavo to buy or sell a quantity of digital assets at a specific price.
:param market: the market to place the order for. For example, `BTC-EUR`.
:param side: either 'buy' or 'sell' in `market`.
:param order_type: the character of the order. For example, a `stopLoss` order type is an instruction to
buy or sell a digital asset in `market` when it reaches the price set in `body`.
:param body: the parameters for the call. For example, {'amount': '0.1', 'price': '2000'}.
"""
body['market'] = market
body['side'] = side
body['orderType'] = order_type
return self.private_request(method='POST', endpoint='/order', body=body)
def private_request(self, endpoint: str, body: dict | None = None, method: str = 'GET'):
"""
Create the headers to authenticate your request, then make the call to Bitvavo API.
:param endpoint: the endpoint you are calling. For example, `/order`.
:param body: for GET requests, this can be an empty string. For all other methods, a string
representation of the call body.
:param method: the HTTP method of the request.
"""
now = int(time.time() * 1000)
sig = self.create_signature(now, method, endpoint, body)
url = self.base + endpoint
headers = {
'bitvavo-access-key': self.api_key,
'bitvavo-access-signature': sig,
'bitvavo-access-timestamp': str(now),
'bitvavo-access-window': str(self.access_window),
}
r = requests.request(method=method, url=url, headers=headers, json=body)
return r.json()
def create_signature(self, timestamp: int, method: str, url: str, body: dict | None):
"""
Create a hashed code to authenticate requests to Bitvavo API.
:param timestamp: a unix timestamp showing the current time.
:param method: the HTTP method of the request.
:param url: the endpoint you are calling. For example, `/order`.
:param body: for GET requests, this can be an empty string. For all other methods, a string
representation of the call body. For example, for a call to `/order`:
`{"market":"BTC-EUR","side":"buy","price":"5000","amount":"1.23", "orderType":"limit"}`.
"""
string = str(timestamp) + method + '/v2' + url
if (body is not None) and (len(body.keys()) != 0):
string += json.dumps(body, separators=(',', ':'))
signature = hmac.new(self.api_secret.encode('utf-8'), string.encode('utf-8'), hashlib.sha256).hexdigest()
return signature
You use Bitvavo SDKs to easily execute your advanced trading strategies from your app. These wrapper SDKS do all the hard work for you, enabling you to rapidly integrate Bitvavo functionality and start trading. Bitvavo SDKs enable you to call every REST endpoint in Bitvavo API, or use WebSocket to subscribe to the latest data and rapidly trade.
To easily integrate Bitvavo into your app, use the following SDKs:
Retrieve the market data that is used by your algorithms for trading.
An order is an instruction made by a Bitvavo user to buy or sell a quantity of digital assets at a specific
price. The order price is given as a specific amount in base currency or quote currency, or a specific
price-per-unit in quote currency.
When a sell order made by one user matches a buy order by another user, Bitvavo fills the buy order and sell order in a trade. Each order may be filled by executing one or multiple trades. When the complete quantity in one order cannot be filled exactly with the other order, Bitvavo progressively completes the larger order with multiple trades. An order is partially filled when there is still an open quantity left on the order book. For example, multiple buy fills for one sell fill. An order is filled when the full quantity in the buy or sell order is matched by fills.
The market name is the combination of the:
A taker is a Bitvavo user who fills a buy or sell order made by a maker. A maker is the Bitvavo user who made the initial order.
Retrieve the list of bids
and asks
for market
. That is, the buy and sell orders made by all Bitvavo users
in a specific market. The orders in the return parameters are sorted by price
.
Rate limit weight points: 1
Websocket action: getBook
market required | string Example: BTC-EUR The market you want the order book for. Call GET /markets to retrieve the list of markets available on Bitvavo. |
depth | integer Return the top |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')() bitvavo.book('BTC-EUR', {}, (error, response) => { if (error === null) { for (let entry of response.bids) { console.log('Bids: ', entry) } for (let entry of response.asks) { console.log('Asks: ', entry) } } else { console.log(error) } })
{- "market": "BTC-EUR",
- "nonce": 438524,
- "bids": [
- [
- "4999.9",
- "0.015"
], - [
- "4999.8",
- "0.015"
], - [
- "4999.7",
- "0.015"
], - [
- "4999.6",
- "0.015"
], - [
- "4999.5",
- "0.015"
], - [
- "4999.4",
- "0.015"
], - [
- "4999.3",
- "0.015"
], - [
- "4999.2",
- "0.015"
], - [
- "4999.1",
- "0.015"
], - [
- "4999",
- "0.015"
]
], - "asks": [
- [
- "5001.1",
- "0.015"
], - [
- "5001.2",
- "0.015"
], - [
- "5001.3",
- "0.015"
], - [
- "5001.4",
- "0.015"
], - [
- "5001.5",
- "0.005"
], - [
- "5001.6",
- "0.005"
], - [
- "5001.7",
- "0.005"
], - [
- "5001.8",
- "0.005"
], - [
- "5001.9",
- "0.005"
], - [
- "5002",
- "0.005"
]
]
}
Retrieve the list of all trades made by all Bitvavo users for market
. That is, the trades that have been executed
in the past.
When a sell order made by one user matches a buy order by another user, Bitvavo fills the buy order and sell order in a trade. Each order may have multiple trades.
To retrieve the list of your trades, call GET /trades. To
retrieve the IDs of the trades associated with an order, see the fills
field in the response
parameters for GET /orders.
Rate limit weight points: 5
Websocket action: getTrades
market required | string Example: BTC-EUR The market you want the trades for. Call GET /markets to retrieve the list of markets available on Bitvavo. |
limit | integer [ 1 .. 1000 ] Default: 500 Return the You use |
start | integer <unix-timestamp in milliseconds> >= 0 Return |
end | integer <unix-timestamp in milliseconds> <= 8640000000000000 Return |
tradeIdFrom | string Return |
tradeIdTo | string Return |
tradeId | string Deprecated Deprecated: use |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')() // All optional parameters are used to limit the results. bitvavo.publicTrades('BTC-EUR', {}, (error, response) => { if (error === null) { console.log('Trade: ', response) } else { console.log(error) } })
[- {
- "id": "57b1159b-6bf5-4cde-9e2c-6bd6a5678baf",
- "timestamp": 1542967486256,
- "amount": "0.1",
- "price": "34,243",
- "side": "sell"
}
]
Retrieve the Open, High, Low, Close, Volume (OHLCV)
data you use to create candlestick charts
for market
with interval
time between each candlestick.
Candlestick data is always returned in chronological data from newest to oldest. Data is returned when trades are
made in the interval
represented by that candlestick. When no trades occur you see a gap in data flow, zero trades
are represented by zero candlesticks.
Rate limit weight points: 1
Websocket action: getCandles
market required | string Example: BTC-EUR The market you want candlestick data for. Call GET /markets to retrieve the list of markets available on Bitvavo. |
interval required | string Enum: "1m" "5m" "15m" "30m" "1h" "2h" "4h" "6h" "8h" "12h" "1d" Define the time interval between each candlestick. |
limit | integer [ 1 .. 1440 ] Default: 1440 Return a maximum of the |
start | integer <unix-timestamp in milliseconds> >= 0 Return a maximum of Candlestick data is always returned in chronological data from newest to oldest. For example, a call to https://api.bitvavo.com/v2/INJ-EUR/candles?interval=1h&limit=4&start=1710489600000 returns:
That is, the candlestick at |
end | integer <unix-timestamp in milliseconds> <= 8640000000000000 Return a maximum of Candlestick data is always returned in chronological data from newest to oldest. For example, a call to https://api.bitvavo.com/v2/INJ-EUR/candles?interval=1h&limit=4&end=1710500400000 returns:
That is, the last candlestick returned is the one generated prior to |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')() bitvavo.candles('BTC-EUR', '1h', {}, (error, response) => { if (error === null) { for (let entry of response.candles) { console.log('Timestamp: ', entry[0], ' Open: ', entry[1], ' High: ', entry[2], ' Low: ', entry[3], ' Close: ', entry[4], ' Volume: ', entry[5]) } } else { console.log(error) } })
[- "1538784000000",
- "4999",
- "5012",
- "4999",
- "5012",
- "0.45"
]
Retrieve the price of the latest trades on Bitvavo for all markets or a single market
.
A tick in a market is any change in the price of a digital asset.
Rate limit weight points: 1
Websocket action: getTickerPrice
market | string Example: market=BTC-EUR The market you want the latest trade price for. Call GET /markets to retrieve the list of markets available on Bitvavo. |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')() bitvavo.tickerPrice({}, (error, response) => { if (error === null) { console.log('Current price for', response.market, ':', response.price) } else { console.log(error) } })
[- {
- "market": "BTC-EUR",
- "price": "5003.2"
}
]
Retrieve the highest buy and the lowest sell prices currently available for all markets, or a single market
in
the Bitvavo order book.
Rate limit weight points: 1
Websocket action: getTickerBook
market | string Example: market=BTC-EUR The market you want the best bid and ask information for. |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')() bitvavo.tickerBook({}, (error, response) => { if (error === null) { console.log(response.market, 'book, bid:', response.bid, ' ask:', response.ask) } else { console.log(error) } })
[- {
- "market": "BTC-EUR",
- "bid": "4999.9",
- "bidSize": "0.15",
- "ask": "5003.3",
- "askSize": "0.2"
}
]
Retrieve high, low, open, last, and volume information for trades and orders for a
single market
, or all markets on Bitvavo over the previous 24 hours.
Rate limit weight points:
market
: 1Websocket action: getTicker24h
market | string Example: market=BTC-EUR The market you want the ticker information for. |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')() bitvavo.ticker24h({}, (error, response) => { if (error === null) { for (let object of response) { console.log(object) } } else { console.log(error) } })
[- {
- "market": "BTC-EUR",
- "startTimestamp": 1700490607372,
- "timestamp": 1700576057382,
- "open": "5001.1",
- "openTimestamp": 1700490620146,
- "high": "5003.2",
- "low": "5001.1",
- "last": "5003.2",
- "closeTimestamp": 1700490620146,
- "bid": "4999.9",
- "bidSize": "0.15",
- "ask": "5003.3",
- "askSize": "0.2",
- "volume": "0.15",
- "volumeQuote": "750.2865"
}
]
Place an order to buy or sell digital assets on Bitvavo.
All orders are added to the Bitvavo order book
immediately. You use the orderType parameter to control the conditions under which your order is
filled. While market
and limit
ordersTypes are filled immediately, stop*
and take*
orders are filled
when trigger conditions are met.
You can have a maximum of 100 open orders at any one time in each
market
.
See the Payload Request samples for examples of the parameters you need to set for each orderType.
Rate limit weight points: 1
Websocket action: privateCreateOrder
The desired order to create
market required | string Set the market you want to place the order in. Call GET /markets to retrieve the list of markets available on Bitvavo. Call GET /{market}/book to retrieve the list of |
side required | string Enum: "buy" "sell"
|
orderType required | string Enum: "market" "limit" "stopLoss" "stopLossLimit" "takeProfit" "takeProfitLimit" Set the type of order you want to place. Possible values are:
For limit orders, set |
clientOrderId | string <UUID> Set a personalized UUID for any orderType. For example This value is unique for |
amount | string Set the quantity of base currency to buy or sell for any orderType. Use the GET /assets endpoint to check the decimal precision available for the quantity of base currency you wish to buy or sell. For example, the Use the GET /markets endpoint to check the minimum and maximum amounts you can create a new order for on Bitvavo. Do not set |
amountQuote | string Set the quantity of quote currency to buy or sell for Use the GET /markets endpoint to check the minimum and maximum amounts you can create a new order for on Bitvavo.
Do not set |
price | string Set the price you are offering to buy or sell 1 base currency at in quote currency for You can use a maximum of five digits for When you set |
triggerAmount | string Set the price to buy or sell 1 base currency in quote currency for a For example, when you set To generate a trigger, you must set |
triggerType | string Value: "price" Set to Currently the To generate a trigger, you must set |
triggerReference | string Enum: "lastTrade" "bestBid" "bestAsk" "midPrice" Define the price type that triggers this order to be filled for a Set to one of the following:
To generate a trigger, you must set |
timeInForce | string Default: "GTC" Enum: "GTC" "IOC" "FOK" Set how long any orderType remains active for. Set to one of the following: |
postOnly | boolean Default: false Control the fees you pay on Bitvavo for
|
selfTradePrevention | string Default: "decrementAndCancel" Enum: "cancelBoth" "cancelNewest" "cancelOldest" "decrementAndCancel" Control the way self trading is rolled back on Bitvavo for conflicting orders for any orderType. Self-trading is when the same user is both the buyer and the seller in a trade. That is, when a trade is made, the digital asset does not change beneficial owner. Self-trading is not allowed on Bitvavo. Set to one of the following:
|
disableMarketProtection | boolean Default: false Best practice is to never disable market protection.
Set to By default, market orders are canceled when the next fill price is 10% worse than the best fill price. This prevents you from filling market orders at an undesirable price. Bitvavo uses the following formula for prices at the top of the order book to calculate this difference:
|
responseRequired | boolean Default: true Control the amount of data in the return parameters for any orderType. Set to either:
|
{- "market": "BTC-EUR",
- "side": "buy",
- "orderType": "limit",
- "amount": "10",
- "price": 7000,
- "responseRequired": false,
- "clientOrderId": "2be7d0df-d8dc-7b93-a550-8876f3b393e6"
}
{- "orderId": "1be6d0df-d5dc-4b53-a250-3376f3b393e6",
- "clientOrderId": "2be7d0df-d8dc-7b93-a550-8876f3b393e9",
- "market": "BTC-EUR",
- "created": 1706100650751,
- "updated": 1706100650751,
- "status": "new",
- "side": "buy",
- "orderType": "limit",
- "amount": "10",
- "amountRemaining": "10",
- "price": "7000",
- "amountQuote": "5000",
- "amountQuoteRemaining": "5000",
- "onHold": "9109.61",
- "onHoldCurrency": "BTC",
- "triggerPrice": "4000",
- "triggerAmount": "4000",
- "triggerType": "price",
- "triggerReference": "lastTrade",
- "filledAmount": "0",
- "filledAmountQuote": "0",
- "feePaid": "0",
- "feeCurrency": "EUR",
- "fills": [
- {
- "id": "371c6bd3-d06d-4573-9f15-18697cd210e5",
- "timestamp": 1542967486256,
- "amount": "0.005",
- "price": "5000.1",
- "taker": true,
- "fee": "0.03",
- "feeCurrency": "EUR",
- "settled": true
}
], - "selfTradePrevention": "decrementAndCancel",
- "visible": true,
- "timeInForce": "GTC",
- "postOnly": true,
- "disableMarketProtection": true
}
Updates a previous placed limit order. Make sure that at least one of the optional parameters is set, otherwise nothing will be updated. This is faster than (and preferred over) canceling orders and creating new orders. During the update your order is briefly removed from the order book.
You must set either orderId
or clientOrderId
. If you set both,
clientOrderId
takes precedence. clientOrderId
is only added in the response when you set it in the request.
Rate limit weight points: 1.
Websocket action: privateUpdateOrder.
market required | string Market for which an order should be updated. |
orderId | string <UUID> Specify the order to update with the You must set either |
clientOrderId | string <UUID> Specify the order to update with the personalized UUID you assigned in the original call to POST /order. You must set either |
amount | |
amountQuote | string Only for market orders: If amountQuote is specified, [amountQuote] of the quote currency will be bought/sold for the best price available. |
amountRemaining | string Updates amountRemaining to this value (and also changes amount accordingly). |
price | string Specifies the amount in quote currency that is paid/received for each unit of base currency. |
triggerAmount | string Only for stop orders: Specifies the amount that is used with the triggerType. Combine this parameter with triggerType and triggerReference to create the desired trigger. |
timeInForce | string Enum: "GTC" "IOC" "FOK" Only for limit orders: Determines how long orders remain active. Possible values: Good-Til-Canceled (GTC), Immediate-Or-Cancel (IOC), Fill-Or-Kill (FOK). GTC orders will remain on the order book until they are filled or canceled. IOC orders will fill against existing orders, but will cancel any remaining amount after that. FOK orders will fill against existing orders in its entirety, or will be canceled (if the entire order cannot be filled). |
selfTradePrevention | string Enum: "decrementAndCancel" "cancelOldest" "cancelNewest" "cancelBoth" Self trading is not allowed on Bitvavo. Multiple options are available to prevent this from happening. The default ‘decrementAndCancel’ decrements both orders by the amount that would have been filled, which in turn cancels the smallest of the two orders. ‘cancelOldest’ will cancel the entire older order and places the new order. ‘cancelNewest’ will cancel the order that is submitted. ‘cancelBoth’ will cancel both the current and the old order. |
postOnly | boolean Only for limit orders: When postOnly is set to true, the order will not fill against existing orders. This is useful if you want to ensure you pay the maker fee. If the order would fill against existing orders, the entire order will be canceled. |
responseRequired | boolean Default: true If this is set to 'true', all order information is returned. Set this to 'false' when only an acknowledgement of success or failure is required, this is faster. |
{- "market": "BTC-EUR",
- "orderId": "95d92d6c-ecf0-4960-a608-9953ef71652e",
- "clientOrderId": "2be7d0df-d8dc-7b93-a550-8876f3b393e9",
- "amount": "1.567",
- "amountQuote": "5000",
- "amountRemaining": "1.560",
- "price": "6000",
- "triggerAmount": "4000",
- "timeInForce": "GTC",
- "selfTradePrevention": "decrementAndCancel",
- "postOnly": true,
- "responseRequired": true
}
{- "orderId": "1be6d0df-d5dc-4b53-a250-3376f3b393e6",
- "clientOrderId": "2be7d0df-d8dc-7b93-a550-8876f3b393e9",
- "market": "BTC-EUR",
- "created": 1706100650751,
- "updated": 1706100650751,
- "status": "new",
- "side": "buy",
- "orderType": "limit",
- "amount": "10",
- "amountRemaining": "10",
- "price": "7000",
- "amountQuote": "5000",
- "amountQuoteRemaining": "5000",
- "onHold": "9109.61",
- "onHoldCurrency": "BTC",
- "triggerPrice": "4000",
- "triggerAmount": "4000",
- "triggerType": "price",
- "triggerReference": "lastTrade",
- "filledAmount": "0",
- "filledAmountQuote": "0",
- "feePaid": "0",
- "feeCurrency": "EUR",
- "fills": [
- {
- "id": "371c6bd3-d06d-4573-9f15-18697cd210e5",
- "timestamp": 1542967486256,
- "amount": "0.005",
- "price": "5000.1",
- "taker": true,
- "fee": "0.03",
- "feeCurrency": "EUR",
- "settled": true
}
], - "selfTradePrevention": "decrementAndCancel",
- "visible": true,
- "timeInForce": "GTC",
- "postOnly": true,
- "disableMarketProtection": true
}
Returns information about an order you placed previously.
You must set either orderId
or clientOrderId
. If you set both, clientOrderId
takes precedence.
Rate limit weight points: 1.
Websocket action: privateGetOrder.
market required | string Example: market=BTC-EUR The market you placed this order in. |
orderId required | string <UUID> Example: orderId=ff403e21-e270-4584-bc9e-9c4b18461465 The UUID assigned by Bitvavo to this order. |
clientOrderId | string <UUID> Example: clientOrderId=2be7d0df-d8dc-7b93-a550-8876f3b393e9 The personalized UUID you assigned to an order. |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')().options({ APIKEY: '<APIKEY>', APISECRET: '<APISECRET>' }) bitvavo.getOrder('BTC-EUR', 'a8d260d8-9228-4bcb-979a-01aeaab4e961', (error, response) => { if (error === null) { console.log(response) } else { console.log(error) } })
{- "orderId": "1be6d0df-d5dc-4b53-a250-3376f3b393e6",
- "clientOrderId": "2be7d0df-d8dc-7b93-a550-8876f3b393e9",
- "market": "BTC-EUR",
- "created": 1706100650751,
- "updated": 1706100650751,
- "status": "new",
- "side": "buy",
- "orderType": "limit",
- "amount": "10",
- "amountRemaining": "10",
- "price": "7000",
- "amountQuote": "5000",
- "amountQuoteRemaining": "5000",
- "onHold": "9109.61",
- "onHoldCurrency": "BTC",
- "triggerPrice": "4000",
- "triggerAmount": "4000",
- "triggerType": "price",
- "triggerReference": "lastTrade",
- "filledAmount": "0",
- "filledAmountQuote": "0",
- "feePaid": "0",
- "feeCurrency": "EUR",
- "fills": [
- {
- "id": "371c6bd3-d06d-4573-9f15-18697cd210e5",
- "timestamp": 1542967486256,
- "amount": "0.005",
- "price": "5000.1",
- "taker": true,
- "fee": "0.03",
- "feeCurrency": "EUR",
- "settled": true
}
], - "selfTradePrevention": "decrementAndCancel",
- "visible": true,
- "timeInForce": "GTC",
- "postOnly": true,
- "disableMarketProtection": true
}
Cancel an open order.
You must set either orderId
or clientOrderId
. If you set both,
clientOrderId
takes precedence.
To find all the orders you have placed that are currently open, call GET /ordersOpen. To filter the orders you want to retrieve, call GET /orders.
Rate limit weight points: This endpoint is not rate limited, if you have reached your rate limit, you can still call this endpoint to cancel an order.
Websocket action: privateCancelOrder.
market required | string Example: market=BTC-EUR Set the market the order you want to cancel is in. Call GET /markets to retrieve the list of markets available on Bitvavo. |
orderId | string <UUID> Example: orderId=ff403e21-e270-4584-bc9e-9c4b18461465 Specify the order to cancel with the You must set either |
clientOrderId | string <UUID> Example: clientOrderId=2be7d0df-d8dc-7b93-a550-8876f3b393e9 Specify the order to update with the personalized UUID you assigned in the original call to POST /order. You must set either |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')().options({ APIKEY: '<APIKEY>', APISECRET: '<APISECRET>' }) bitvavo.cancelOrder('BTC-EUR', 'c8719781-7251-4fd7-9673-cce170e4f33a', (error, response) => { if (error === null) { console.log('We canceled order ', response) } else { console.log(error) } })
{- "orderId": "2e7ce7fc-44e2-4d80-a4a7-d079c4750b61",
- "clientOrderId": "2be7d0df-d8dc-7b93-a550-8876f3b393e9"
}
Returns all current open orders at once.
Rate limit weight points: 25 (without market) or 1 (with market).
Websocket action: privateGetOrdersOpen.
market | string If specified, only orders on this market will be returned. If neither market nor base is specified, all open orders will be returned. |
base | string If specified, only orders in this base asset will be returned. If neither market nor base is specified, all open orders will be returned. |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')().options({ APIKEY: '<APIKEY>', APISECRET: '<APISECRET>' }) bitvavo.ordersOpen({}, (error, response) => { if (error === null) { console.log(response) } else { console.log(error) } })
[- {
- "orderId": "1be6d0df-d5dc-4b53-a250-3376f3b393e6",
- "clientOrderId": "2be7d0df-d8dc-7b93-a550-8876f3b393e9",
- "market": "BTC-EUR",
- "created": 1706100650751,
- "updated": 1706100650751,
- "status": "new",
- "side": "buy",
- "orderType": "limit",
- "amount": "10",
- "amountRemaining": "10",
- "price": "7000",
- "amountQuote": "5000",
- "amountQuoteRemaining": "5000",
- "onHold": "9109.61",
- "onHoldCurrency": "BTC",
- "triggerPrice": "4000",
- "triggerAmount": "4000",
- "triggerType": "price",
- "triggerReference": "lastTrade",
- "filledAmount": "0",
- "filledAmountQuote": "0",
- "feePaid": "0",
- "feeCurrency": "EUR",
- "fills": [
- {
- "id": "371c6bd3-d06d-4573-9f15-18697cd210e5",
- "timestamp": 1542967486256,
- "amount": "0.005",
- "price": "5000.1",
- "taker": true,
- "fee": "0.03",
- "feeCurrency": "EUR",
- "settled": true
}
], - "selfTradePrevention": "decrementAndCancel",
- "visible": true,
- "timeInForce": "GTC",
- "postOnly": true,
- "disableMarketProtection": true
}
]
Returns historic trades for your account.
Rate limit weight points: 5.
Websocket action: privateGetTrades.
market required | string Example: market=BTC-EUR |
limit | integer [ 1 .. 1000 ] Default: 500 Filter used to limit the returned results. Most recent [limit] trades will be returned. |
start | integer <unix-timestamp in milliseconds> >= 0 Integer specifying from (i.e. showing those later in time) which time all orders should be returned. Should be a timestamp in milliseconds since 1 Jan 1970. |
end | integer <unix-timestamp in milliseconds> <= 8640000000000000 Integer specifying up to (i.e. showing those earlier in time) which time all orders should be returned. Should be a timestamp in milliseconds since 1 Jan 1970. |
tradeIdFrom | string Filter used to limit the returned results. All trades after this trade ID are returned (i.e. showing those later in time). |
tradeIdTo | string Filter used to limit the returned results. All trades up to this trade ID are returned (i.e. showing those earlier in time). |
tradeId | string Deprecated Deprecated: tradeId is interpreted as tradeIdTo. Filter used to limit the returned results. All trades up to this trade ID are returned. |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')().options({ APIKEY: '<APIKEY>', APISECRET: '<APISECRET>' }) bitvavo.trades('BTC-EUR', {}, (error, response) => { if (error === null) { console.log(response) } else { console.log(error) } })
[- {
- "id": "108c3633-0276-4480-a902-17a01829deae",
- "orderId": "1d671998-3d44-4df4-965f-0d48bd129a1b",
- "clientOrderId": "2be7d0df-d8dc-7b93-a550-8876f3b393e9",
- "timestamp": 1542967486256,
- "market": "BTC-EUR",
- "side": "buy",
- "amount": "0.005",
- "price": "5000.1",
- "taker": true,
- "fee": "0.03",
- "feeCurrency": "EUR",
- "settled": true
}
]
Returns data for multiple orders at once.
Rate limit weight points: 5.
Websocket action: privateGetOrders.
market required | string Example: market=BTC-EUR |
limit | integer [ 1 .. 1000 ] Default: 500 Filter used to limit the returned results. Most recent [limit] orders will be returned. |
start | integer <unix-timestamp in milliseconds> >= 0 Integer specifying from (i.e. showing those later in time) which time all orders should be returned. Should be a timestamp in milliseconds since 1 Jan 1970. |
end | integer <unix-timestamp in milliseconds> <= 8640000000000000 Integer specifying up to (i.e. showing those earlier in time) which time all orders should be returned. Should be a timestamp in milliseconds since 1 Jan 1970. |
orderIdFrom | string <UUID> Filter used to limit the returned results. All orders after this order ID are returned (i.e. showing those later in time). |
orderIdTo | string <UUID> Filter used to limit the returned results. All orders up to this order ID are returned (i.e. showing those earlier in time). |
orderId | string Deprecated Deprecated: orderId is interpreted as orderIdTo. Filter used to limit the returned results. All orders up to this order ID are returned. |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')().options({ APIKEY: '<APIKEY>', APISECRET: '<APISECRET>' }) bitvavo.getOrders('BTC-EUR', {}, (error, response) => { if (error === null) { console.log(response) } else { console.log(error) } })
[- {
- "orderId": "1be6d0df-d5dc-4b53-a250-3376f3b393e6",
- "clientOrderId": "2be7d0df-d8dc-7b93-a550-8876f3b393e9",
- "market": "BTC-EUR",
- "created": 1706100650751,
- "updated": 1706100650751,
- "status": "new",
- "side": "buy",
- "orderType": "limit",
- "amount": "10",
- "amountRemaining": "10",
- "price": "7000",
- "amountQuote": "5000",
- "amountQuoteRemaining": "5000",
- "onHold": "9109.61",
- "onHoldCurrency": "BTC",
- "triggerPrice": "4000",
- "triggerAmount": "4000",
- "triggerType": "price",
- "triggerReference": "lastTrade",
- "filledAmount": "0",
- "filledAmountQuote": "0",
- "feePaid": "0",
- "feeCurrency": "EUR",
- "fills": [
- {
- "id": "371c6bd3-d06d-4573-9f15-18697cd210e5",
- "timestamp": 1542967486256,
- "amount": "0.005",
- "price": "5000.1",
- "taker": true,
- "fee": "0.03",
- "feeCurrency": "EUR",
- "settled": true
}
], - "selfTradePrevention": "decrementAndCancel",
- "visible": true,
- "timeInForce": "GTC",
- "postOnly": true,
- "disableMarketProtection": true
}
]
Cancel multiple orders at once. Either for an entire market or for the entire account.
Rate limit weight points: This endpoint is not rate limited, if you have reached your rate limit, you can still call this endpoint to cancel an order.
Websocket action: privateCancelOrders.
market | string Example: market=BTC-EUR Filter used to specify for which market orders should be canceled. If market is not specified, all open orders will be canceled. |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')().options({ APIKEY: '<APIKEY>', APISECRET: '<APISECRET>' }) bitvavo.cancelOrders({}, (error, response) => { if (error === null) { console.log(response) } else { console.log(error) } })
[- {
- "orderId": "1be6d0df-d5dc-4b53-a250-3376f3b393e6"
}
]
Returns deposit address (with paymentid for some assets) or bank account information to increase your balance.
Rate limit weight points: 1.
Websocket action: privateDepositAssets.
symbol required | string Short version of the asset name to deposit. |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')().options({ APIKEY: '<APIKEY>', APISECRET: '<APISECRET>' }) bitvavo.depositAssets('BTC', (error, response) => { if (error === null) { console.log(response) } else { console.log(error) } })
{- "address": "CryptoCurrencyAddress",
- "paymentid": "10002653"
}
Returns the deposit history of the account.
Rate limit weight points: 5.
Websocket action: privateGetDepositHistory.
symbol | string Optional filter used to specify for which asset the deposit history should be returned. When no symbol is specified, all deposits will be returned. |
limit | integer [ 1 .. 1000 ] Default: 500 Filter used to limit the returned results. Most recent [limit] deposits will be returned. |
start | integer <unix-timestamp in milliseconds> >= 0 Integer specifying from (i.e. showing those later in time) which time all deposits should be returned. Should be a timestamp in milliseconds since 1 Jan 1970. |
end | integer <unix-timestamp in milliseconds> <= 8640000000000000 Integer specifying up to (i.e. showing those earlier in time) which time all deposits should be returned. Should be a timestamp in milliseconds since 1 Jan 1970. |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')().options({ APIKEY: '<APIKEY>', APISECRET: '<APISECRET>' }) bitvavo.depositHistory({}, (error, response) => { if (error === null) { console.log(response) } else { console.log(error) } })
{- "timestamp": 1706609321000,
- "symbol": "BTC",
- "amount": "0.99994",
- "address": "14qViLJfdGaP4EeHnDyJbEGQysnCpwk3gd",
- "paymentId": "10002653",
- "txId": "927b3ea50c5bb52c6854152d305dfa1e27fc01d10464cf10825d96d69d235eb3",
- "fee": "0.000063"
}
Request a withdrawal to an external cryptocurrency address or verified bank account. Please note that 2FA and address confirmation by e-mail are disabled for API withdrawals.
Rate limit weight points: 1.
Websocket action: privateWithdrawAssets.
The desired withdrawal to create
symbol required | string Short version of asset name to withdraw. |
amount required | string The amount to be withdrawn. |
address required | string Wallet address or IBAN. For digital assets: please double check this address. Funds sent can not be recovered. |
paymentId | string For digital assets only. Payment IDs are used to identify transactions to merchants and exchanges with a single address. This is mostly called a note, memo or tag. Should be set when withdrawing straight to another exchange or merchants that require payment id's. |
internal | boolean Default: false This parameter is deprecated and should be omitted or set to false in your request. Setting this value to true will produce the following error: Internal transfer is not possible. |
addWithdrawalFee | boolean Default: false If set to true, the fee will be added on top of the requested amount, otherwise the fee is part of the requested amount and subtracted from the withdrawal. |
{- "symbol": "BTC",
- "amount": "1.5",
- "address": "BitcoinAddress",
- "paymentId": "10002653",
- "internal": false,
- "addWithdrawalFee": false
}
{- "success": true,
- "symbol": "BTC",
- "amount": "1.5"
}
Returns the withdrawal history.
Rate limit weight points: 5.
Websocket action: privateGetWithdrawalHistory.
symbol | string Optional filter used to specify for which asset the withdrawal history should be returned. When no symbol is specified, all deposits will be returned. |
limit | integer [ 1 .. 1000 ] Default: 500 Filter used to limit the returned results. Most recent [limit] withdrawals will be returned. |
start | integer <unix-timestamp in milliseconds> >= 0 Integer specifying from (i.e. showing those later in time) which time all withdrawals should be returned. Should be a timestamp in milliseconds since 1 Jan 1970. |
end | integer <unix-timestamp in milliseconds> <= 8640000000000000 Integer specifying up to (i.e. showing those earlier in time) which time all withdrawals should be returned. Should be a timestamp in milliseconds since 1 Jan 1970. |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')().options({ APIKEY: '<APIKEY>', APISECRET: '<APISECRET>' }) bitvavo.withdrawalHistory({}, (error, response) => { if (error === null) { console.log(response) } else { console.log(error) } })
{- "timestamp": 1542967486256,
- "symbol": "BTC",
- "amount": "0.99994",
- "address": "BitcoinAddress",
- "paymentId": "10002653",
- "txId": "927b3ea50c5bb52c6854152d305dfa1e27fc01d10464cf10825d96d69d235eb3",
- "fee": "0.00006",
- "status": "awaiting_processing"
}
Returns the current fees for this account.
Rate limit weight points: 1.
Websocket action: privateGetAccount.
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')().options({ APIKEY: '<APIKEY>', APISECRET: '<APISECRET>' }) bitvavo.account((error, response) => { if (error == null) { console.log(response) } else { console.log(error) } })
{- "fees": {
- "taker": "0.0025",
- "maker": "0.0015",
- "volume": "10000.00"
}
}
Returns the current balance for this account.
Rate limit weight points: 5.
Websocket action: privateGetBalance.
symbol | string Filter used to specify for which asset the balance should be returned. If symbol is omitted, all assets with a non-zero balance are returned plus those traded at least once. |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')().options({ APIKEY: '<APIKEY>', APISECRET: '<APISECRET>' }) bitvavo.balance({}, (error, response) => { if (error === null) { console.log(response) } else { console.log(error) } })
[- {
- "symbol": "BTC",
- "available": "1.57593193",
- "inOrder": "0.74832374"
}
]
Retrieve the fees you are charged for trading in a specific market.
With trading fees ranging from 0.00% to 0.25%, Bitvavo's fees are among the lowest in the industry. The
fee tier you are member of is dependant on your total trading volume over the past 30
days in all markets. For example, if you traded €26 million on Bitvavo over the last 30 days, you are in tier 8 in
the Bitvavo fee structure.
The trading fee you are charged depends on the Category that market
is included in. For example, if your trading
volume puts you in tier 8, the taker fee you are charged to trade a Category B asset is 0.04%.
In Category A the taker fee is 0.02%.
Rate limit weight points: 1
Websocket action: privateGetFees
market | string Example: market=BTC-EUR The market you want your fee information for. Leave this parameter empty to retrieve the fee for your current tier in Category B. Call GET /markets to retrieve the list of markets available on Bitvavo. |
quote | string Enum: "EUR" "USDC" The quote currency you want your fee information for. Leave this parameter empty to retrieve the fee for your current tier in Category B. |
{ "action" : "privateGetFees" "market" : "BTC-EUR" }
{- "tier": "0",
- "volume": "10000.00",
- "taker": "0.0025",
- "maker": "0.0015"
}
Returns the transaction history for this account.
Rate limit weight points: 1.
Websocket action: privateGetTransactionHistory.
fromDate | integer <unix-timestamp in milliseconds> >= 0 The start date for the transaction history. |
toDate | integer <unix-timestamp in milliseconds> <= 8640000000000000 The end date for the transaction history. |
page | integer >= 1 The page number for the transaction history. |
maxItems | integer [ 1 .. 100 ] The maximum number of items per page in the transaction history. |
type | string Enum: "sell" "buy" "staking" "deposit" "withdrawal" "affiliate" "distribution" "internal_transfer" "withdrawal_cancelled" "rebate" "loan" "external_transferred_funds" The type of transaction. |
{- "items": [
- {
- "transactionId": "5f5e7b3b-4f5b-4b2d-8b2f-4f2b5b3f5e5f",
- "executedAt": "2021-01-01T00:00:00.000Z",
- "type": "sell",
- "priceCurrency": "EUR",
- "priceAmount": "1000.00",
- "sentCurrency": "EUR",
- "sentAmount": "0.1",
- "receivedCurrency": "BTC",
- "receivedAmount": "0.0001",
- "feesCurrency": "EUR",
- "feesAmount": "0.01",
- "address": "string"
}
], - "currentPage": 1,
- "totalPages": 1,
- "maxItems": 100
}
Synchronize information with your app. Including the markets and assets traded on Bitvavo.
Returns the current timestamp in milliseconds since 1 Jan 1970. This can be useful if you need to synchronize your time with Bitvavo's servers.
Rate limit weight points: 1.
Websocket action: getTime.
import javaBitvavoApi.Bitvavo; Bitvavo bitvavo = new Bitvavo(); System.out.println("Current time is " + bitvavo.time().getLong("time"));
{- "time": 1539180275424
}
Retrieve information about one or all markets on Bitvavo.
Rate limit weight points: 1
Websocket action: getMarkets
market | string Example: market=BTC-EUR The market you want data about. |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')() // If all markets should be returned, pass an empty options object. bitvavo.markets({}, (error, response) => { if (error === null) { for (let object of response) { console.log('Market response: ', object) } } else { console.log(error) } })
[- {
- "market": "BTC-EUR",
- "status": "trading",
- "base": "BTC",
- "quote": "EUR",
- "pricePrecision": "5",
- "minOrderInBaseAsset": "0.0001",
- "minOrderInQuoteAsset": "5",
- "maxOrderInBaseAsset": "1000000000",
- "maxOrderInQuoteAsset": "1000000000",
- "orderTypes": [
- "market",
- "limit",
- "stopLoss",
- "stopLossLimit",
- "takeProfit",
- "takeProfitLimit"
]
}
]
Returns information on the supported assets. An optional filter can be passed to limit the results.
Rate limit weight points: 1.
Websocket action: getAssets.
symbol | string Example: symbol=BTC Filter used to specify for which asset data should be returned. |
// The Javascript SDK works with callbacks and with promises. For info, check our GitHub. const bitvavo = require('bitvavo')() bitvavo.assets({}, (error, response) => { if (error === null) { for (let object of response) { console.log('Asset: ', object) } } else { console.log(error) } })
[- {
- "symbol": "BTC",
- "name": "Bitcoin",
- "decimals": 8,
- "depositFee": "0",
- "depositConfirmations": 10,
- "depositStatus": "OK",
- "withdrawalFee": "0.2",
- "withdrawalMinAmount": "0.2",
- "withdrawalStatus": "OK",
- "networks": [
- "Mainnet"
], - "message": ""
}
]
To implement low-latency, high-frequency trading, you interact with Bitvavo using WebSocket. In a hurry? WebSocket is implemented for you in the Bitvavo SDKs.
All REST endpoints in Bitvavo API are available using WebSocket. The base
URL for Bitvavo WebSocket is wss://ws.bitvavo.com/v2/
, and you encode
all messages to the WebSocket in a JSON object. For all endpoints, you
pass the same parameters as the REST requests in the JSON object, plus the
action
parameter to specify the endpoint. For example, the HTTP GET
request to retrieve data about a specific market,
https://api.bitvavo.com/v2/markets?market=AION-EUR
is written as:
{
"action":"getMarkets",
"market":"AION-EUR"
}
The WebSocket action is listed with each endpoint in this page. For example, GET /markets.
With WebSocket, to easily associate the return parameters with your
initial request, use the requestId
parameter. Bitvavo inserts the
integer value of requestId
with the return parameters for the action.
For example, a call to:
{
"action":"getMarkets",
"market":"AION-EUR",
"requestId": 4051979
}
returns:
{
"action": "getMarkets",
"response": {
"market": "AION-EUR",
"status": "halted",
"base": "AION",
"quote": "EUR",
"pricePrecision": 5,
"minOrderInBaseAsset": "10",
"minOrderInQuoteAsset": "5",
"maxOrderInBaseAsset": "1000000000",
"maxOrderInQuoteAsset": "1000000000",
"orderTypes": [
"market",
"limit",
"stopLoss",
"stopLossLimit",
"takeProfit",
"takeProfitLimit"
]
},
"requestId": 4051979
}
To receive updates using WebSocket, subscribe to one or more of the following channels:
[price, size]
are sent to this channel. Use this and getBook to maintain a local copy of the Bitvavo order books.The subscribe
and unsubscribe
actions require a channels
parameter.
This is a list of JSON objects. Each object has a:
book
.["BTC-EUR"]
.["1h"]
. This is only for candles.For example:
{
"action": "subscribe",
"channels": [
{
"name": "candles",
"interval": [
"1h"
],
"markets": [
"BTC-EUR"
]
},
{
"name": "book",
"markets": [
"BTC-EUR",
"XRP-EUR"
]
}
]
}
The following events are emitted for the subscribed channels: order
,
fill
, book
, trade
, ticker
, ticker24h
, candle
. The
authenticate
, unauthenticate
, subscribed
and unsubscribed
events
are sent after authentication or
(un)subscribe messages.
To securely connect to Bitvavo in a WebSocket, you must send a message that provides authentication for the duration of the connection. For example:
{
"action": "authenticate",
"key": "ExampleKey",
"signature": "653fc0505431c63a043273da4bd2f0927eae83948d796084f313e5d1131b0d6f",
"timestamp": 1548175200641
}
This JSON object has the following parameters:
action: authenticate
.
key: Your API Key.
signature: A signature generated following the REST
specification with a GET request to
/v2/websocket
and no body.
For example, If timestamp
is 1548175200641
, and secret
is bitvavo
. This string, 1548175200641GET/v2/websocket
results in the following signature
653fc0505431c63a043273da4bd2f0927eae83948d796084f313e5d1131b0d6f
.
timestamp: The current timestamp in milliseconds since 1 Jan 1970.
For example: 1548175200641
.
window (optional) : The time in milliseconds that your request is allowed to execute in. The default value is 10000 (10s), the maximum value is 60000 (60s).
Receive the latest information about markets, and market trades in your WebSocket callback.
Subscribes to the ticker channel, which returns an object each time the best bid or ask changes.
action required | string The action that should be performed by the websocket server, "subscribe" is used for all subscriptions. |
required | Array of objects Object containing the desired subscriptions. |
{- "action": "subscribe",
- "channels": [
- {
- "name": "ticker",
- "markets": [
- "BTC-EUR"
]
}
]
}
{- "event": "subscribed",
- "subscriptions": {
- "ticker": [
- "BTC-EUR"
]
}
}
Subscribes to the ticker 24 hour channel, which returns an object every second, if values have changed.
action required | string The action that should be performed by the websocket server, "subscribe" is used for all subscriptions. |
required | Array of objects Object containing the desired subscriptions. |
{- "action": "subscribe",
- "channels": [
- {
- "name": "ticker24h",
- "markets": [
- "BTC-EUR"
]
}
]
}
{- "event": "subscribed",
- "subscriptions": {
- "ticker": [
- "BTC-EUR"
]
}
}
Subscribes to candle data and returns a candle each time a new one is formed.
action required | string The action that should be performed by the websocket server, "subscribe" is used for all subscriptions. |
required | Array of objects Object containing the desired subscriptions. |
{- "action": "subscribe",
- "channels": [
- {
- "name": "candles",
- "markets": [
- "BTC-EUR"
], - "interval": [
- "1m"
]
}
]
}
{- "event": "subscribed",
- "subscriptions": {
- "candles": {
- "1h": [
- "BTC-EUR"
]
}
}
}
Subscribes to the trades channel, which sends an object whenever a trade has occurred.
action required | string The action that should be performed by the websocket server, "subscribe" is used for all subscriptions. |
required | Array of objects Object containing the desired subscriptions. |
{- "action": "subscribe",
- "channels": [
- {
- "name": "trades",
- "markets": [
- "BTC-EUR"
]
}
]
}
{- "event": "subscribed",
- "subscriptions": {
- "trades": [
- "BTC-EUR"
]
}
}
Subscribes to the book and returns a delta on every change to the book.
action required | string The action that should be performed by the websocket server, "subscribe" is used for all subscriptions. |
required | Array of objects Object containing the desired subscriptions. |
{- "action": "subscribe",
- "channels": [
- {
- "name": "book",
- "markets": [
- "BTC-EUR"
]
}
]
}
{- "event": "subscribed",
- "subscriptions": {
- "book": [
- "BTC-EUR"
]
}
}
Receive the latest information about your trades and your account in your WebSocket callback.
The channels
you create with a subscribe
action send an event to your WebSocket every time there is an update related to orders you placed on Bitvavo in the markets
you specify.
Each trading subscription WebSocket receives the following events:
Subscribe: confirmation that the channel you created to receive order and fill events for specific markets has been created.
Order: receive a JSON object containing data about every order you created or updated with calls to
POST /order,
PUT /order,
DELETE /order or
DELETE /orders in the markets
you subscribed to in this
channel.
Fill: receive a JSON object containing data about every partial or complete fill
or trade
executed for an order you
placed on Bitvavo in the markets
you subscribed to in this channel.
action required | string Set to subscribe to receive information about the fills and trades related to the orders you make in the |
required | Array of objects Listen for trading events in one or more markets in one or more channels. |
{- "action": "subscribe",
- "channels": [
- {
- "name": "account",
- "markets": [
- "BTC-EUR",
- "ETH-BTC",
- "ETH-EUR"
]
}
]
}
{- "event": "subscribed",
- "subscriptions": {
- "channel-name": [
- "BTC-EUR",
- "ETH-BTC",
- "ETH-EUR"
]
}
}
Each REST endpoint and WebSocket action in Bitvavo API is allocated Rate limit weight points.
For example, a call to POST /order uses 1
weight point.
For each call to Bitvavo, Rate limit weight points is subtracted from bitvavo-ratelimit-limit
, leaving
bitvavo-ratelimit-remaining
until bitvavo-ratelimit-resetat
.
For authenticated users, if you use more than bitvavo-ratelimit-limit
points in one minute, Bitvavo returns
error code 110 in an HTTP 429 response and your account is blocked for 1 minute.
For unauthenticated users, the IP used to make calls to Bitvavo is blocked for 15 minutes.
When you make a REST call to Bitvavo API, rate limit information is returned in the following headers:
bitvavo-ratelimit-remaining
: your remaining weight points until the counter resets.bitvavo-ratelimit-resetat
: the timestamp when the counter resets.bitvavo-ratelimit-limit
: your allocated weight points per minute. The default value is 1000
.The rate limit applies to the sum of all calls made using REST and WebSocket. When you use WebSocket in your trading app, rate limit information is not sent to your callback. Make REST calls to keep track of your weight points.
Although you can connect to Bitvavo with multiple WebSockets in parallel, each WebSocket is limited to 5000 requests per second. If you exceed the request limit, Bitvavo returns error code 112 in an HTTP 429 response and your account is blocked for 1 minute.
If you use Bitvavo SDKs, track your weight points with calls to:
limit = bitvavo.getRemainingLimit()
This section contains information about all possible error messages returned by Bitvavo. Each error message is associated with one of the following HTTP status messages:
The following table explains the reason for each errorCode
returned by Bitvavo with a HTTP 400 status code:
errorCode | Reason |
---|---|
102 | The JSON object you sent is invalid. |
200 | Path parameters are not accepted for this endpoint. Take care, parameters are case-sensitive. |
201 | Body parameters are not accepted for this endpoint. Take care, query parameters are case-sensitive. |
202 | A parameter in your call to POST | PUT /order is not supported for this orderType . For example, you cannot set price for a market , stopLoss , or takeProfit orderType. |
203 | Either you did not include a required parameter in you request, or you included incompatible parameters. For example, in a call to POST /order, market is required, amount and amountQuote are incompatible. |
204 | You used a parameter that is not in the parameter list for this endpoint. |
205 | The value you set for a parameter is incorrect. For example, in a call to GET /{market}/candles you set interval to 6d , which is not in the interval enum. |
206 | You set incompatible parameters in your call. For example, in a call to GET /orders you set orderIdTo and orderIdFrom . |
210 | The value of amount in your POST | PUT /order request is greater than maxOrderInBaseAsset . To see the highest value allowed for amount in market , call GET /markets. |
211 | The value of price in your POST | PUT /order request is greater than 100000000000 . |
212 | The value of amount in your POST | PUT /order request is lower than minOrderInBaseAsset . To see the lowest value allowed for amount in market , call GET /markets. |
213 | The value of price in your POST | PUT /order request is lower than 0.000000000000001 . |
214 | The value of price in your POST | PUT /order request has too many significant digits. See pricePrecision in GET /markets for the maximum number of significant digits. |
215 | The value of price in your POST | PUT /order request has more than 15 digits after the decimal point. |
216 | Your balance is not sufficient to perform this operation. |
217 | The value of amountQuote in your POST | PUT /order request is lower than minOrderInQuoteAsset . To see the lowest value allowed for amountQuote in market , call GET /markets. |
218 | The value of triggerAmount in your POST | PUT /order request has too many significant digits. See pricePrecision , in GET /markets for the maximum number of significant digits. |
219 | The market you want to trade in your POST | PUT /order is no longer listed on Bitvavo. |
220 | Conflict |
231 | When markets are paused, you must set timeInForce to GTC in your POST | PUT /order request. |
232 | For your PUT /order request to be successful, change one or more of amount , amountRemaining , price , timeInForce , selfTradePrevention or postOnly . |
233 | To DELETE /order, the value of status in the return parameters for this order must be new or partiallyFilled . |
234 | You cannot PUT /order a market orderType. |
235 | You can have a maximum of 100 open orders at any one time in each market . |
236 | You can set one only of amount , amountRemaining , or amountQuote when you call PUT /order for any orderType . |
237 | You must set one of amount , amountRemaining , amountQuote , triggerAmount or selfTradePrevention when you call PUT /order for a stopLoss orderType. |
238 | You must set one of amount , amountRemaining , price , triggerAmount , timeInForce , selfTradePrevention or postOnly when you call PUT /order for a stopLossLimit orderType. |
239 | You cannot swap between amount and amountQuote when you update an order. For example, when you set amount in your call to POST /order, you cannot update amountQuote in subsequent calls to PUT /order. |
400 | Server error |
401 | Deposits for this asset are not available at this time. |
402 | Verify your identity before you deposit or POST /withdraw digital assets. |
403 | Verify your phone number before you deposit or POST /withdraw digital assets. |
404 | Could not complete this operation. Internal server error. |
405 | You cannot POST /withdraw digital assets during the cooldown period. The cooldown period may also apply after you add a new bank account. |
406 | The value of amount in your POST /withdraw request is below the minimum allowed value. To see the lowest amount allowed for symbol , call GET /assets. |
407 | Internal transfer is not possible. |
408 | Your balance is not sufficient to perform this operation. |
409 | Please verify your bank account and try again. |
410 | You cannot POST /withdraw for this asset at the moment. |
411 | You cannot transfer assets to yourself. |
412 | Error when you attempted to deposit or POST /withdraw digital assets. |
413 | The IP address set for address in your POST /withdraw request is not in your IP whitelist. |
414 | You cannot withdraw assets within 2 minutes of logging in. |
The following table explains the reason for each errorCode
returned by Bitvavo with a HTTP 403 status code:
errorCode | Reason |
---|---|
105 | You have exceeded your Rate limit. If your calls to Bitvavo are authenticated, your account is blocked for 1 minute. If your calls are unauthenticated, the IP this call was made from is blocked for 15 minutes. |
300 | Setup REST or WebSocket authentication to successfully call this endpoint. |
301 | The API key you use for REST or WebSocket authentication must be 64 characters long. |
302 | The access timestamp you set for REST or WebSocket authentication must be in milliseconds. For example, 1709904125666. |
303 | The access window you set for REST or WebSocket authentication must be between 100 and 60000 milliseconds. |
304 | Your request was not received within the access window you set for REST or WebSocket authentication. |
305 | The API key used for this call is not active. |
306 | The API key used for this call is not active. Ensure that you have confirmed the API key. |
307 | The IP this call was made from is not in the whitelist for this API key. |
308 | The signature you use for REST or WebSocket authentication must be a 64 character hexadecimal string. |
309 | The signature you use for REST or WebSocket authentication is invalid. |
310 | This API key does not have permissions to use the Trading endpoints. |
311 | This API key does not have permissions to use the Account endpoints. |
312 | This API key does not have permissions to Withdraw assets. |
313 | Your Bitvavo session is not valid. |
314 | You must use REST to connect from a browser. |
316 | You can use this WebSocket to retrieve public information about assets only. |
317 | This account is locked. Please contact support@bitvavo.com. |
318 | You must verify your account to use Bitvavo API for Rest and WebSocket. |
319 | This feature is unavailable in your region due to regulatory constraints. |
The following table explains the reason for each errorCode
returned by Bitvavo with a HTTP 404 status code:
errorCode | Reason |
---|---|
110 | Unknown REST endpoint. Please check the URL and HTTP method called against the Bitvavo API reference. |
240 | No order found. This error can happen when you call POST /order and PUT /order at the same time. |
415 | Unknown WebSocket action. Please check the action called against the Bitvavo API reference |
The following table explains the reason for each errorCode
returned by Bitvavo with a HTTP 409 status code:
errorCode | Reason |
---|---|
110 | The clientOrderId in your call to POST /order already exists in market . |
The following table explains the reason for each errorCode
returned by Bitvavo with a HTTP 429 status code:
errorCode | Reason |
---|---|
110 | You have exceeded your Rate limit by making too many calls to Bitvavo in the last minute. |
112 | You have exceeded your Rate limit of 5000 requests per WebSocket per second. |
The following table explains the reason for each errorCode
returned by Bitvavo with a HTTP 500 status code:
errorCode | Reason |
---|---|
101 | Unknown error. This call to Bitvavo may or may not have succeeded. |
The following table explains the reason for each errorCode
returned by Bitvavo with a HTTP 503 status code:
errorCode | Reason |
---|---|
107 | Bitvavo is overloaded. Please wait 500ms and resubmit your call. |
108 | Bitvavo could not process your oder. Please either increase the execution window in your REST or WebSocket implementation or wait 500ms and resubmit your call. |
109 | Bitvavo did not respond on time. This operation may or may not have succeeded. |
Q: Are order and cancel requests via WebSocket faster than via REST calls?
A: Yes, according to our measurements WS is faster than REST.
Q: I have noticed that sometimes it is not possible to sell digital coins due to the minimum transaction value.
My trading bot often incorrectly gives a minimum value error message. How often is this minimum value adjusted to match current market values?
A: To find the minimum amount for a transaction, call GET /markets and use the values minOrder*
in the return parameters and check againstyour balance. see the API docs.
For high frequency trading, one thing to remember is that when you make an order on Bitvavo, the onHold amount of onHoldCurrency is blocked.
After the trades are completed, there is a slight lag until the trading fees are charged.
Q: Is it possible to increase the rate limit of my API key?
A: When you are ready for high volume trading, please send a specific request to support explaining the volume of trading you expect to make, and we will be happy to accommodate. The more you trade, the cheaper it is to trade on Bitvavo, have a look at the API docs to see how this works, and see the fee structure here.
Q: Do you have any documentation on failure responses for REST or WebSocket requests?
A: We have our API docs that describes the error codes: link 1, link 2
Q: The documentation on "Trading Rules" states that scheduled downtime will be communicated to users via account.bitvavo.com.
Do you have an API endpoint for announcements that we can use to get notifications of downtime?
A: At the moment we don't have such an endpoint.
Q: Is a matching engine restart a common occurrence, or part of a scheduled downtime?
A: Usually the restart of a matching engine (ME) happens during the scheduled downtime or when something goes wrong and the ME is being restarted.
Q: I would like to understand whether I will see the nonce value reset/decrease during the lifetime of a WebSocket session.
A: The nonce value should never decrease during the lifetime of a matching engine. However, it is reset on restart of the engine. This means that you can expect that nonce could be reset during the lifetime of WS sessions.
Q: I've started working on connecting to Bitvavo and found out that rejection messages for the orders do not have any information about which order was rejected. I subscribed for 'account' channel, and it doesn't have any rejection messages:
{
"action": "privateCreateOrder",
"market": "BTC-EUR",
"errorCode": 216,
"error": "You do not have sufficient balance to complete this operation."
}
There is no way to distinguish orders in WebSocket. Is it possible to add clientOrderId to rejection messages?
A: You can add a requestId to their request to trace the order.
Q: I had a read of the docs and I see there's a TimeInForce field in the update message.
Is it possible to insert a GFD and later amend the TimeInForce?
A: No, it is not possible to amend the TimeInForce. We don't have a GFD, its GTC by default.
Q: How do I request my available euro balance via API? Should I use the Account balance endpoint with EUR symbol?
A: Yes! Here are the API docs that describe how to do it.
Q: In trades, there is timestamp (milliseconds). Is it matching engine time?
A: It’s the time when the trade occurred in UTC.
Q: Can you please clarify the following transaction types returned by the transaction history endpoint.
A: The transaction of some types are:
Q: Is there any benefit to authenticating WebSocket connections used for receiving market data events?
A: The rate limits is higher for authenticated users. Please refer to the rate limits documentation for more information.
Q: Is there any speed advantage of using an authenticated WebSocket connection if I only use endpoints that don't require authentication.
A: No there is no any speed advantage, but it is better to use an authenticated WebSocket connection to have proper rate limits.
Q: Is it delta update for the full book for WebSocket book subscription or is it limited to some range?
A: We don't limit the depth for the order book event, we handle the event as we get it from a matching engine (ME).
Q: What is the maximum number of Websocket connections one account can open?
A: We don't have a limit in place but the rate limit is shared between all open connections.
Q: Are the WebSocket updates published to any subscribed session identical in terms of their payload?
For example, for two sessions subscribed to BTC-EUR, will they always receive the same updates containing the same nonce value, and exact same price updates?
A: It is the expected behaviour that all clients receive the same updates.
Q: If a matching engine(ME) is restarted (causing the nonce to decrease), would any existing market data WebSocket(WS) connections be disconnected,
or do WS connections stay connected while the ME is restarted?
A: WS will stay connected. WS can be used for different markets and actions.
Q: What is the behaviour of Bitvavo API if a market data WebSocket consumer cannot keep up with the rate of updates being published by API?
Will the packets be dropped by API side (leading to a gap in the nonce value), or disconnect the connection?
A: WebSocket(WS) is built on top of TCP (i.e. all packets are delivered in order and there's checks for packet loss). The server can buffer messages to a point, but the bottom line is since WS operates over TCP the server doesn't drop packets. Messages not being processed are usually due to client-side limitations or network issues, not server-side packet drops. If the buffer fills up, the server might slow down the message rate or as a last resort disconnect the connection. For reconnection and buffered messages, consumers should implement appropriate handling.
Q: Sometimes when I am losing some of my WebSocket connections, and I am trying to reconnect I receive the following errors: Handshake status 429 Too Many Requests
A: It's good to check whether the reconnection is attempted in multiple threads, or on a loop without waiting for the response of the server. Also, check if you are sharing the IP with someone else, for instance a private VPN network.
Q: Can I rely on a deterministic ordering of fill & order events?
For example, when a fill occurs on Bitvavo, does a WebSocket session see an order, then fill event (or vice versa), and will this ordering always be consistent?
A: We don't provide any guarantees for ordering here, unfortunately. We have a distributed and concurrent environment, so sometimes we have to sacrifice determinism in favor of minimizing latency.
Q: Is it guaranteed that a fill-event from the WebSocket trading subscription will be received only after a response for createOrder event?
A: You might want to set the responseRequired flag to false when you create an order to get the minimal acknowledgement of success or failure ASAP (along with the orderId). It's technically possible for a fill event to happen before a createOrder response even if responseRequired is set to false because these are two separate processes. But typically setting the flag to false results in a much faster response time, so it's very unlikely that a fill event precedes an order response.
Q: Is it possible for a fill event to be faster than order event?
A: There is no ordering guarantee in a matching engine (ME) at the moment as to which response will be sent first. Under normal conditions it should be the createOrder response first as fill event is sent on settlement but there are no guarantees.
Q: The response samples in the API docs, are these the same for Websocket responses?
A: Yes, the response samples are the same for WebSocket and REST APIs.
Q: When I subscribe for message on the websocket, I do that via a REST call? Is it also possible to send a subscribe message directly over the websocket?
A: WebSocket protocol works over HTTP. You need to open a WebSocket connection and send the request with actions that they want. There is API doc about WS API https://docs.bitvavo.com/#tag/WebSocket.
You could consider to use one of our SDKs. There is the link with the description of SDKs - https://docs.bitvavo.com/#tag/SDKs
Q: Is it possible to transfer transaction costs in euros internally via the API? So from one Bitvavo user to another Bitvavo user?
A: Unfortunately, the answer is not possible. You can transfer between internal wallets for digital assets only.
Euro transactions are sent to your IBAN which in its nature is external to Bitvavo.
Fees for any transaction on Bitvavo are charged just after the operation has taken place. For example, just after a trade has taken place or a transaction made.
In the case of asset withdrawal. Please see the internal
and addWithdrawalFee
parameter in POST methods.
Q: I have read in the documentation that it is necessary to disable the cryptocurrency withdrawal lock to allow withdrawals to external wallets.
However, I noticed that even with this lock activated, transfers to internal wallets at Bitvavo are also not possible.
I would like to know if there is a way to facilitate internal transfers without disabling this lock.
A: To withdraw assets using the API you have to assign the Withdraw digital assets permission to your API key. When you withdraw using the API 2FA and address confirmation by e-mail are disabled.
Q: Withdrawals of digital coins, both internally and externally, can only take place if a crypto address has been added to your address book. How does that work with an internal (from Bitvavo user to another Bitvavo user) transfer?
A: You should set the wallet address in POST methods.
Q: Is there a weight difference in a WebSocket subscription request if I subscribe to multiple markets in a single request?
A: No. The difference in the request composition is only for ticker24 and open orders. They are more expensive if no market is specified.
Q: What is the weight of a WebSocket subscription request and is it different per subscription. i.e. does OrderBook have a different weight to Ticker or Trades?
A: No, they all have the default point. YOu can find the exact weight of each request in the API docs.
The following changes have been made to Bitvavo API:
Use the new Transaction History endpoint to retrieve the transaction history of your account. This endpoint allows you to filter transactions by type, and date range.
Use the new Fees endpoint to retrieve the transaction costs you are charged for trading in a specific market.
Improve order status tracking with the clientOrderID
parameter:
clientOrderId
personalized UUID you set for each
New order.clientOrderId
is returned in the response parameters for the Trading subscription WebSocket.