# Bitvavo API documentation — full content > Concatenated body of every page indexed at https://docs.bitvavo.com/llms.txt. > Regenerated on every deploy. Mirrors the section order of /llms.txt. Bitvavo API docs provide spot trading, market data, transfers, and account management through REST, WebSocket, and FIX APIs. Authenticate with HMAC-SHA256 signatures — REST signs each request, WebSocket signs an authenticate message after connecting, and FIX signs the Logon message. Each API's introduction page has the signing details. --- ## Overview Source: https://docs.bitvavo.com/docs/overview/ Bitvavo provides programmatic access to its exchange through multiple APIs, designed for automated trading, real-time market data, and account management. These APIs are intended for professional and algorithmic traders who need reliable execution, low-latency data, and fine-grained control over their trading infrastructure. ### What you can build Using the Bitvavo APIs, you can: - Create, update, and cancel orders - Stream real-time market data and account events - Maintain a clean local order book - Synchronize balances, trades, and positions - Manage accounts and subaccounts programmatically ### What we support #### Trading APIs ##### [Exchange REST API](/docs/rest-api/introduction/) - Best suited for synchronous, request-response interactions - Commonly used for order management, account queries, and historical data ##### [Exchange WebSocket API](/docs/websocket-api/introduction/) - Event-driven API for real-time updates - Used for streaming market data and account-level events ##### [FIX API](/docs/fix-api/introduction/) - Low-latency, session-based protocol - Intended for high-frequency and institutional trading workflows #### Market Data APIs ##### [Market Data Pro WebSocket API](/docs/ws-market-data-pro-api/introduction/) - High-throughput real-time market data streams - Designed for professional trading systems that require full-depth data #### Institutional APIs ##### [Account Management REST API](/docs/institutional-api/introduction/) - Manage multiple accounts and view consolidated balances ##### [Subaccounts REST API](/docs/institutional-api/get-balance/) - Access balances and transaction history for individual subaccounts ### Next steps - **[Get started](/docs/get-started/)** with your API credentials and authenticate your first request - Choose a protocol to build your integration: - [REST API](/docs/rest-api/introduction/) - [WebSocket API](/docs/websocket-api/introduction/) - [FIX API](/docs/fix-api/introduction/) ### See also - [Get started](/docs/get-started/) - [Order lifecycle](/docs/order-lifecycle/) - [Manage local order book](/docs/manage-order-book/) - [Cancel on disconnect](/docs/cancel-on-disconnect/) - [Stream data with WS Market Data Pro](/docs/ws-market-data-pro-sync/) - [Handle errors](/docs/errors/) - [Rate limits](/docs/rate-limits/) --- ## Get started Source: https://docs.bitvavo.com/docs/get-started/ Use the instructions below to set up your Bitvavo account, create development credentials, and learn how to authenticate your requests. ### Before you start Before you start integrating, make sure you have: - [Signed up for a Bitvavo account](#sign-up-for-a-bitvavo-account) - [Enabled two-factor authentication](#enable-two-factor-authentication) - [Created an API key and secret](#create-an-api-key-and-secret) #### Sign up for a Bitvavo account Before you start building your trading app, make sure you have either a _private_ or a _corporate_ Bitvavo account. - To sign up for a private account, go to the [Bitvavo website](https://account.bitvavo.com/create). If you need help, see [Creating an account](https://support.bitvavo.com/hc/en-us/articles/4405230499601-How-do-I-create-a-private-account). - To sign up for a corporate account, contact `professional@bitvavo.com` for more information about eligibility and the onboarding process. #### Enable two-factor authentication 1. [Log in](https://bitvavo.com/) to your Bitvavo account. 2. Under your account, select **Security**. 3. Under **Two-factor authentication**, select **Enable 2FA**. 4. Enter your Bitvavo account password.
A QR code displays on the screen. 5. Scan the QR code with an authenticator app, like **Google Authenticator**. 6. Enter the 6-digit 2FA code from your authenticator app. 7. Select **Confirm**.
Your Bitvavo account is now protected with two-factor authentication. #### Create an API key and secret 1. Log in to your [Bitvavo account](https://bitvavo.com/). 2. Under your account, select **Settings**. 3. In the **API** tab, select **Add new API key**. 4. Enter: - Your **Name** for the API key. - Under **IP Whitelist**, the IP address from which you want to make API requests. :::tip Whitelisting your IP address prevents your account from being accessed if your API credential is stolen. ::: 5. Select the permissions for your API key: - **View access**: view account information, including balances and transactions. - **Trade digital assets**: create, update, and cancel orders. - **Withdraw digital assets**: withdraw digital assets to an external address or a verified bank account. :::warning Withdrawals made using Bitvavo API **do not** require 2FA and e-mail confirmation. ::: - **Include all subaccounts**: cancel orders and retrieve information for your subaccounts. - **Internal Transfer**: transfer assets between your subaccounts and the main account. - **Administrative**: create and view subaccounts under your main account. 6. Enter the **2FA** code and select **Confirm**. :::warning Make sure to store your API key and secret in a secure location. You cannot retrieve it later. ::: ### See also - [Authentication for Exchange REST API](/docs/rest-api/introduction/) - [Authentication for Exchange WebSocket API](/docs/websocket-api/introduction/) - [Authentication for Market Data Pro WebSocket API](/docs/ws-market-data-pro-api/introduction/) - [Order lifecycle](/docs/order-lifecycle) --- ## Order lifecycle Source: https://docs.bitvavo.com/docs/order-lifecycle/ The order lifecycle begins when you create an order and it gets an `orderId`. Depending on the `orderType`, it start in either `new` or `awaitingTrigger` status. To track your orders status changes in real time, we recommend using the [Track your orders](/docs/websocket-api/track-your-orders/) WebSocket channel. You can also make requests to our REST API to [get all open orders](/docs/rest-api/get-open-orders/) or the status of a [single order](/docs/rest-api/get-order/). To track the status of your order, you use the `orderId`, but you can also assign it your own `clientOrderId`. When tracking orders, you should: - Track the `orderId` and the latest [`status`](#order-status). - Check [partial fills](#track-your-orders). - Check different [cancellation reasons](#completed-orders). - Monitor events that follow. ### Order types Bitvavo supports different types of orders to help you manage your trades. To do this from your app, you make requests to create, update, or cancel orders using the [REST](/docs/rest-api/create-order/) or [WebSocket](/docs/websocket-api/create-order/) APIs. You can create the following types of orders by setting the `orderType` parameter in your request: - **market**: executes immediately by matching with the best-priced and oldest available order in the order book. - **limit**: executes only when the market price meets or improves upon the set limit price. - **stopLoss**: creates a market order to buy or sell when the trigger price is met to prevent further losses. - **stopLossLimit**: triggers a limit order instead of a market order when the price meets the stop level, to prevent further losses. - **takeProfit**: creates a market order to buy or sell when the price meets the set level to ensure profits. - **takeProfitLimit**: like take profit but uses a limit order instead of a market order to ensure profits. ### Order status From creation to completion, orders move through different statuses. To understand the lifecycle of an order, you need to know that there are two categories of `status`: - [Active orders](#active-orders): orders that are open and can be filled. - [Completed orders](#completed-orders): orders that are filled or canceled by the system or the user. #### Order lifecycle The diagram below shows the sequence of status changes of an order. import Mermaid from '@theme/Mermaid'; new [*] --> awaitingTrigger new --> filled new --> partiallyFilled new --> canceled new --> expired partiallyFilled --> filled partiallyFilled --> canceled partiallyFilled --> expired awaitingTrigger --> new awaitingTrigger --> canceled filled --> [*] expired --> [*] canceled --> [*] `} /> :::info Orders can be canceled for different reasons. Check the specific [canceled order](#completed-orders) status to learn more. ::: #### Active orders When you [create an order](/docs/rest-api/create-order/), it gets an `orderId`. An order starts in either the `new` status, or `awaitingTrigger` if you put a condition when to trigger the execution. If it is only partially filled, an order remain active and waits for more matching orders to be completely filled. Alternatively, a market order can also end up in an `expired` status if there is no match, enough liquidity in the order book, or enough balance in your account. The active statuses are: | Status | Description | Can move to | |:-------------------|:----------------------------------------------------------------------------------|:----------------------------------------------------| | `new` | The order is in the order book and is waiting for a matching order. | `filled` , `partiallyFilled`, `canceled`, `expired` | | `awaitingTrigger` | The condition to execute is not met. When met, the status moves to `new`. | `new`, `canceled` | | `partiallyFilled` | A part of the order is filled. More matching orders are needed to fill the order. | `filled` , `canceled`, `expired` | While still active, you can [update](/docs/rest-api/update-order/) or [cancel](/docs/rest-api/cancel-order/) your orders. :::tip We recommend using the [Track your orders](/docs/websocket-api/track-your-orders/) WebSocket channel to track the status of your orders in real time. ::: #### Completed orders For orders that are no longer active, we return the following statuses: - `filled`: all trades necessary to complete the order have been filled. - `expired`: the market order expires because there is no match, enough liquidity in the order book, or enough balance in your account. Also, if you set the `timeInForce` parameter to **IOC** or **FOK** for your order, the order can expire if those conditions are not met. - `canceled`: the `orderId` is removed from the order book by either you or Bitvavo. ##### Canceled orders When an order is canceled, you can get the reason in the `restatementReason` parameter of the response to the following requests: - REST API: [Create order](/docs/rest-api/create-order), [Update order](/docs/rest-api/update-order), [Get order](/docs/rest-api/get-order/), [Get orders](/docs/rest-api/get-orders/), and [Get open orders](/docs/rest-api/get-open-orders/). - WebSocket API: [Create order](/docs/websocket-api/create-order), [Update order](/docs/websocket-api/update-order), [Get order](/docs/websocket-api/get-order/), [Get orders](/docs/websocket-api/get-orders/), [Get open orders](/docs/websocket-api/get-open-orders/), and [Track your orders](/docs/websocket-api/track-your-orders/). Depending on the mechanism that canceled the order, the `restatementReason` parameter returns one of the following values: - `decrementOnSelfTradePrevention`: the order was partially filled and the remaining amount was decremented to prevent self-trade. - `cancelOnSelfTradePrevention`: we canceled the order to prevent self-trade. - `cancelOnPlacementPriceProtection`: placement price protection check canceled the order was canceled because it was outside the acceptable price range. - `cancelOnExecutionPriceProtection`: execution price protection check canceled the limit order because it was outside the current market range. - `cancelOnSpreadProtection`: spread price protection check canceled the market order because it was outside the acceptable range. - `cancelOnReferencePriceProtection`: reference price protection check canceled the order because it was outside the acceptable price range compared to the index price. - `cancelPostOnlyOnAuctionMatching`: we canceled the order because it was a post-only order and the market was in the `auctionMatching` status. - `cancelOnMaintenance`: we canceled the order because the market was in the `maintenance` status. - `cancelOnDisconnect`: cancel on disconnect mechanism canceled the order because the connection was lost or there was no heartbeat. - `cancelOnDelisting`: the order was canceled because the market was delisted. - `cancelOnLockPlaced`: the order was canceled because the market was locked. - `cancelOnAdminRequest`: an administrator canceled the order. - `cancelPostOnly`: we canceled the order because it was a post-only order and the market was in the `cancelOnly` status. ### Track your orders The best way to track your partially filled orders is to subscribe to the [Track your orders](/docs/websocket-api/track-your-orders) WebSocket channel. You then compare the values of the total `amount` and the `amountRemaining` parameters to learn how much of your order has been filled and is still open. :::info You can also use the REST API to get the status of a [single](/docs/rest-api/get-order/) or [all open orders](/docs/rest-api/get-open-orders/). However, it is not real-time and can consume your [rate limits](/docs/rate-limits/) quickly if your app makes frequent requests. ::: ### Prevent self-trade [Self-trading is not allowed on Bitvavo](https://bitvavo.com/en/trading-rules). An order from one account cannot be matched with an order from the same account. To prevent self-trade, you can set the `selfTradePrevention` parameter in your [order request](/docs/rest-api/create-order/) to one of the following values: - `cancelOldest`: cancels the earlier order. - `cancelNewest`: cancels the later order. - `cancelBoth`: cancels both orders. - `decrementAndCancel`: decreases the amount of the conflicting order by the difference between the buy and sell orders. Cancels the lower order. ### Market status The status of the market also impacts the execution of orders. A market can be in one of the following statuses: - `trading`: open for trading. - `halted`: closed for trading. You cannot create, update, or cancel orders. - `auction`: in transition from closed to open. You cannot create market orders. You can create other order types, but there is still no matching. - `auctionMatching`: the opening price is calculated. Orders created during the auction phase that meet the final opening price are matched and executed. - `cancelOnly`: you can only cancel orders and cannot create or update orders. :::info To check the status of the market, make a *Get markets* request to the [REST](/docs/rest-api/get-markets/) or [WebSocket](/docs/websocket-api/get-markets/) API to receive latest updates about the market status. ::: ### Price protection Bitvavo enforces a set of pre-trade checks to safeguard market integrity, maintain orderly markets, and protect customers from clearly erroneous trades. These checks are always active and protect users and the order book from fat finger errors, unintended market behavior, or manipulative actions. The following checks are always active: - **Placement price protection**: Good-Till-Canceled (GTC) limit orders outside the acceptable price range are canceled. For instance, if the BTC-EUR mid-point price is 100,000€ (the average between the best bid and best ask in the order book) and the threshold multiplier is 5, buy orders below 20,000€ and sell orders above 500,000€ are automatically canceled. - **Execution price protection**: Good-Till-Canceled (GTC), Immediate-or-Cancel (IOC), and Fill-or-Kill (FOK) limit orders outside the current market range are canceled. For example, if the BTC-EUR mid-point price is 100,000€ and the threshold is 80%, buy orders above 180,000€ and sell orders below 20,000€ are canceled. - **Spread price protection**: Market orders are prevented from executing at prices outside the acceptable range. For example, the best bid in BTC-EUR is 100,000€ and the threshold is 4%. The sell orders in the book are 1BTC at 100,010€, 5BTC at 102,000€, 1BTC at 103,000€ and 10BTC at 105,000€. In a market order to buy 10BTC, 1BTC is filled at 100,010€, 5BTC at 102,000€, 1BTC at 103,000€, and the remaining 4BTC are canceled. - **Reference price protection**: Orders outside the acceptable price range compared to the index price are partially or fully canceled. For example, the reference protection threshold is 10% and the reference price is 100,000€. The sell orders in the book are 1BTC at 100,010€, 5BTC at 102,000€, 1BTC at 103,000€ and 10BTC at 111,000€. A limit order to buy 10 BTC at 115,000€, fills for 1BTC at 100,010€, 5BTC at 102,000€, and 1BTC at 103,000€ and the remaining 3BTC are canceled. When canceled by a price protection check, orders end up in the [status](#completed-orders) specific to the check that canceled them. ### Next steps - [Create an order](/docs/rest-api/create-order/) - [Update an order](/docs/rest-api/update-order/) --- ## Manage local order book Source: https://docs.bitvavo.com/docs/manage-order-book/ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; If you are keeping track of the order book locally, it is important to keep it in sync with Bitvavo. This prevents inaccurate trading caused by stale or out-of-sequence data and ensures your orders reflect the latest market conditions. This is especially important for high-frequency trading strategies that rely on real-time data and trade on multiple exchanges. ### Prerequisites Before you start, make sure you have: - [Signed up for a Bitvavo account](/docs/get-started/#sign-up-for-a-bitvavo-account) - [Enabled two-factor authentication](/docs/get-started/#enable-two-factor-authentication) - [Created an API key and secret](/docs/get-started/#create-an-api-key-and-secret) ### Step 1: Subscribe to order book updates 1. Connect to the [WebSocket API](/docs/websocket-api/introduction/) using the `wss://ws.bitvavo.com/v2/` endpoint. 2. Subscribe to the [Book subscription channel](/docs/websocket-api/book-subscription/) for a market (for example, `BTC-EUR`). ```json title="WebSocket subscription message" { "action": "subscribe", "channels": [ { "name": "book", "markets": ["BTC-EUR"] } ] } ``` 3. Store (buffer) the incoming events ordered by the value of the `nonce` parameter. This is a sequential identifier of the order book version. ```json title="Book subscription event" { "event": "book", "market": "BTC-EUR", "nonce": 123456789, "bids": [ [ "30000.50", "0.1" ], [ "30000.00", "0.5" ] ], "asks": [ [ "30001.00", "0.2" ], [ "30001.50", "0.3" ] ] } ``` ### Step 2: Get a snapshot of the order book 1. To get a snapshot of the order book, make a **Get order book** [REST API](/docs/rest-api/get-order-book/) or [WebSocket](/docs/websocket-api/get-order-book/) request for a market. ```curl title=" cURL request" curl -L -g 'https://api.bitvavo.com/v2/{market}/book' \ -H 'Accept: application/json' \ -H 'Bitvavo-Access-Key: YOUR_API_KEY' \ -H 'Bitvavo-Access-Timestamp: YOUR_GENERATED_SIGNATURE' \ -H 'Bitvavo-Access-Signature: CURRENT_TIMESTAMP' \ -H 'Bitvavo-Access-Window: 10000' \ ``` ```json title=" getBook message" { "action": "getBook", "requestId": 1, "market": "BTC-EUR", "depth": 3 } ``` The response for REST and WebSocket is the same: ```json title="Snapshot" { "market": "BTC-EUR", "nonce": 123456788, "bids": [ [ "30000.50", "0.1" ], [ "30000.00", "0.6" ], [ "29999.50", "0.2" ] ], "asks": [ [ "30001.00", "0.2" ], [ "30001.50", "0.3" ], [ "30002.00", "0.1" ] ] } ``` 3. Compare the `nonce` of the snapshot with the `nonce` of the initial WebSocket update: - If the value `nonce` of the snapshot is greater than the `nonce` from the first update, go to [Step 3](#step-3-update-your-local-order-book). - If the `nonce` of the snapshot is smaller than or equal to the `nonce` from the first update, get a new snapshot and try again. 4. Discard all stored updates where the `nonce` of the event is smaller than or equal to the `nonce` from the snapshot. ### Step 3: Update your local order book 1. Update the `bids` and `asks` in your order book to the state from the snapshot. 2. Set the update ID of your order book to the `nonce` of the snapshot. 3. Apply the remaining stored updates with a `nonce` greater than the `nonce` of the snapshot. 4. Continue to apply new WebSocket updates, using the update procedure below. ### Step 4: Discard outdated data 1. If the `nonce` of the event is not greater exactly by **1** than the `nonce` of your local order book, your local book is out of sync. Discard it and restart the process from [Step 1](#step-1-subscribe-to-order-book-updates) (re-subscribe and get a new snapshot). 2. For every price in `bids` and `asks`: - If the price is not in your local book, add it with the provided size (for example, price level `"30000.50"` and size `"0.1"`). - If the size is `0`, remove the price from your local book. - If the price already exists, update its size to the new value. 3. After applying all updates from the event, set the `nonce` of your local book to match the `nonce` of the event. ### See also - [WebSocket API](/docs/websocket-api/) - [REST API](/docs/rest-api/) - [Stream data with WS Market Data Pro](/docs/ws-market-data-pro-sync/) --- ## Cancel on disconnect Source: https://docs.bitvavo.com/docs/cancel-on-disconnect/ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; In case of network outages, extreme latency, or similar issues your orders can remain open and be filled at unfavorable prices while you are disconnected. To prevent this, you can use *Cancel on disconnect* which automatically cancels your open orders if there is no activity from you within a set period of time. :::info You cannot use *Cancel on disconnect* for market orders. ::: ### How it works 1. You send a `cancelOrdersAfter` request to: - Create a group identifier for new orders: `codGroupId`. - Set the time countdown timer after which the orders are canceled: `expiryAfterSeconds`. 4. You create orders and add that `codGroupId` in the body of the requests. 5. You keep sending `cancelOrdersAfter` requests to reset the countdown timer. 6. If there is no `cancelOrdersAfter` message from you before the countdown timer expires, we cancel all open orders with that `codGroupId`. Orders that are cancelled on disconnect always have **cancelOnDisconnect** specified as their [restatementReason](/docs/order-lifecycle/#completed-orders). ### Prerequisites Before you start, make sure you have: - [Signed up for a Bitvavo account](/docs/get-started/#sign-up-for-a-bitvavo-account) - [Enabled two-factor authentication](/docs/get-started/#enable-two-factor-authentication) - [Created an API key and secret](/docs/get-started/#create-an-api-key-and-secret) Also, be sure to read the Authentication instructions for [WebSocket](/docs/websocket-api/introduction/) and [REST API](/docs/rest-api/introduction/). ### Step 1: Create a codGroupId Firstly, you need to create a group identifier that you can specify when creating new orders. This enables *Cancel on disconnect* for those open orders and sets the countdown timer after which the orders are automatically canceled. To create a group identifier: 1. Send either a [WebSocket](/docs/websocket-api/cancel-orders-after/) or [REST API](/docs/rest-api/cancel-orders-after/) request to create a `codGroupId`. 2. In the body of the request specify: - `codGroupId`: your identifier for a group of orders. - `expiryAfterSeconds`: your countdown timer in seconds after which open orders are canceled. The minimum allowed value is **10**. ```json title="privateCancelOrdersAfter" { "action": "privateCancelOrdersAfter", "codGroupId": 1, "expiryAfterSeconds": 30, "requestId": 1 } ``` ```bash title="POST /cancelOrdersAfter" curl -L 'https://api.bitvavo.com/v2/order' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Bitvavo-Access-Key: ' \ -H 'Bitvavo-Access-Timestamp: ' \ -H 'Bitvavo-Access-Signature: ' \ -H 'Bitvavo-Access-Window: ' \ -d '{ "codGroupId": 1, "expiryAfterSeconds": 30 }' ``` 3. The `codGroupId` is created with the `timeOfExpirySeconds` countdown timer in the number of seconds you specified. You can now specify that `codGroupId` when [creating new orders](#create-orders-cod) to enable the *Cancel on disconnect*. ### Step 2: Create orders with the codGroupId {/* #create-orders-cod */} After you have created a `codGroupId`, you can create orders as usual with either the WebSocket or REST API. To add an order to a group: 1. Send either a [WebSocket](/docs/websocket-api/create-order/) or [REST API](/docs/rest-api/create-order/) request to create an order. 2. In the body of the request specify the `codGroupId` parameter with the value you created. ```json title="privateCancelOrdersAfter" { "action": "privateCreateOrder", "requestId": 1, "market": "BTC-EUR", "side": "buy", "orderType": "market", "operatorId": 543462, "clientOrderId": "2be7d0df-d8dc-7b93-a550-8876f3b393e9", "amount": "1.567", "amountQuote": "5000", "price": "6000", "triggerAmount": "4000", "triggerType": "price", "triggerReference": "lastTrade", "timeInForce": "GTC", "postOnly": false, "selfTradePrevention": "decrementAndCancel", "responseRequired": true, "codGroupId": 1 } ``` ```bash title="POST /cancelOrdersAfter" curl -L 'https://api.bitvavo.com/v2/order' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Bitvavo-Access-Key: ' \ -H 'Bitvavo-Access-Timestamp: ' \ -H 'Bitvavo-Access-Signature: ' \ -H 'Bitvavo-Access-Window: ' \ -d '{ "market": "BTC-EUR", "side": "buy", "orderType": "market", "operatorId": 543462, "clientOrderId": "string", "amount": "1.567", "amountQuote": "5000", "price": "6000", "triggerAmount": "4000", "triggerType": "price", "triggerReference": "lastTrade", "timeInForce": "GTC", "postOnly": false, "selfTradePrevention": "decrementAndCancel", "responseRequired": true, "codGroupId": 1 }' ``` 3. An order is created in the order book and added to the `codGroupId` you specified. *Cancel on disconnect* is now active for your order. You now have to keep sending requests periodically to [reset the countdown timer](#step-3-reset-the-countdown-timer). If you want to disable *Cancel on disconnect*, you need to [remove the group](#remove-the-group). ### Step 3: Reset the countdown timer To reset the countdown timer you can use the same request that you used to create the `codGroupId`: 1. Send either a [WebSocket](/docs/websocket-api/cancel-orders-after/) or [REST API](/docs/rest-api/cancel-orders-after/) request. 2. In the request body, specify the `codGroupId` you want to send the heartbeat for. 3. Keep sending requests to before the specified countdown timer expires. :::tip To prevent consuming your [rate limits](/docs/rate-limits/), avoid sending reset messages too often. For example, if you set the `expiryAfterSeconds` to **30** seconds, we recommend that you send a reset message *once* every **15** seconds. ::: For example: - You send a [WebSocket](/docs/websocket-api/cancel-orders-after/) message: ```json title="privateCancelOrdersAfter" { "action": "privateCancelOrdersAfter", "codGroupId": 1, "expiryAfterSeconds": 30, "requestId": 12 } ``` - If successful, the countdown timer resets and you receive the **200 OK** response: ```json title="privateCancelOrdersAfter response" { "action": "privateCancelOrdersAfter", "requestId": 12, "response": { "codGroupId": 1, "timeOfExpirySeconds": 17202139111 } } ``` - If it fails, the countdown timer does not reset and you receive the **400 Bad Request** response: - `errorCode`: this is always **433** - `error`: description of the reason. Can be: - `limit of group ids is reached`: **the maximum of number of groups** - `invalid group id`: **the invalid `groupId` provided** - `invalid expiryAfterSeconds`: **the invalid value** ```json title="error response" { "errorCode":433, "error": "limit of group ids is reached: 5" } ``` If this happens, to reset the countdown timer, you need to send a new `cancelOrdersAfter` message with the correct parameters depending on the `rejectionReason` you received. Possible rejection reasons are: - `LIMIT_REACHED`: you have reached the maximum number of groups you can create. Wait for one of the existing groups to expire or [remove a group](#remove-the-group). - `INVALID_GROUP_ID`: check the `codGroupId` and send the request again. - `INVALID_EXPIRY_AFTER_SECONDS`: check the `expiryAfterSeconds` value and send the request again. ### (Optional) Remove the group {/* #remove-the-group */} If you want to disable *Cancel on disconnect* but keep your orders open, you can remove the group you created. Those orders will no longer have a countdown timer. However, be aware that removing the group does not automatically remove the `codGroupId` parameter from those open orders. This is important because you can reuse the `codGroupId` to create a new group. If you use the same `codGroupId` to create a new group, the open orders that already have that `codGroupId` **will not** have cancel on disconnect enabled. To remove a group: 1. Send either a [WebSocket](/docs/websocket-api/cancel-orders-after/) message or [REST API](/docs/rest-api/cancel-orders-after/) request and specify: - `codGroupId`: the group identifier you want to remove. - `expiryAfterSeconds`: set this to **0**. ```json title="privateCancelOrdersAfter" { "action": "privateCancelOrdersAfter", "codGroupId": 1, "expiryAfterSeconds": 0, "requestId": 2 } ``` ```bash title="POST /cancelOrdersAfter" curl -L -X POST 'https://api.bitvavo.com/v2/cancelOrdersAfter' \ -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Bitvavo-Access-Key: ' \ -H 'Bitvavo-Access-Timestamp: ' \ -H 'Bitvavo-Access-Signature: ' \ -H 'Bitvavo-Access-Window: ' \ -d '{ "codGroupId": 1, "expiryAfterSeconds": 0 }' ``` 2. If successful, you receive the **200 OK** response and your `codGroupId` is removed. Your orders with that `codGroupId` stay open in the order book. --- ## Stream data with WS Market Data Pro Source: https://docs.bitvavo.com/docs/ws-market-data-pro-sync/ The [WebSocket Market Data Pro](/docs/ws-market-data-pro-api/) API provides *non-conflated Level 2 (L2)* market data with *sequence numbering* that allows you to track every change in the order book exactly as it happens. You can then use this data to process live updates and handle potential data gaps to ensure your local book is always in sync with Bitvavo’s state. ### Why use WS Market Data Pro You should stream data using WS Market Data Pro if you: - Need [real-time, full-fidelity market data](#improved-latency) - Want to [detect and handle missed or out-of-order updates](#advanced-sequence-tracking) automatically If you only need conflated updates or a simpler feed, you can continue using the standard [WebSocket](/docs/websocket-api/) and [REST](/docs/rest-api/) APIs. To learn how to use them, see [Manage local order book](/docs/manage-order-book/). #### Improved latency {/* #improved-latency */} The [WS Market Data Pro](/docs/ws-market-data-pro-api/) streams events about *47.5 milliseconds faster* than the standard WebSocket API. This provides almost *9 times more messages* to ensure a smoother, more accurate view of the market. | **Latency Comparison** | **Standard WebSocket** | **Market Data Pro** | |-------------------------|---------------------------|-------------------------------| | **Average delay** | ~100 ms (batched updates) | ~52.5 ms faster (non-batched) | | **Update frequency** | 1 message / 100 ms | ~9.1 messages / 100 ms | | **Price reactivity** | Single delayed update | Instant, multi-point updates | | **Feed behavior** | Buffered | Real-time | To compare the streams of book events between the two WebSocket APIs, we simulated activity near the top of the order books. We then measured how long it took for the changes to appear in the book subscriptions. You can see the comparison in the graph below. The orange line (*WS Market Data Pro*) reacts instantly to market movements, while the blue line (*standard WebSocket*) shows a delay caused by batching. ![latency](../static/img/latency.png) #### Advanced sequence tracking {/* #advanced-sequence-tracking */} The standard [WebSocket API](/docs/websocket-api/) uses a single `nonce` field to help you detect missed updates. While this works for basic use cases, it can be challenging to identify exactly which events are missing when gaps occur. The [Market Data Pro](/docs/ws-market-data-pro-api/) API introduces a start–end sequence range model that provides more robust event tracking: - `mdSeqNo`: The sequence number of the last event applied to that snapshot - `startMdSeqNo` and `endMdSeqNo`: The range of events covered by that update message - `type`: All events now include a `type: "update"` field for forward compatibility This range-based model gives you explicit verification of the complete sequence. While `startMdSeqNo` and `endMdSeqNo` are typically equal (representing a single event), they can differ when the system groups multiple events into one message under high load. For example: - Update with `startMdSeqNo: 101` and `endMdSeqNo: 102` confirms that events 101 and 102 are both included - The next message begins with `startMdSeqNo: 103` This makes it easier to [detect gaps and recover from missed updates](#troubleshoot-and-recover), ensuring your local order book stays in sync with Bitvavo. :::caution WS Market Data Pro `nonce` values are *not shared* with REST or standard WebSocket APIs. ::: ### Sync your local order book {/* #sync-your-local-order-book */} #### Prerequisites Before you start, make sure you’ve done the following: - [Signed up for a Bitvavo account](/docs/get-started/#sign-up-for-a-bitvavo-account) - [Enabled two-factor authentication](/docs/get-started/#enable-two-factor-authentication) - [Created an API key and secret](/docs/get-started/#create-an-api-key-and-secret) - Can [authenticate your connection](/docs/ws-market-data-pro-api/introduction/) to WS Market Data Pro API #### Step 1: Subscribe to order book updates {/* #step-1-subscribe-to-order-book-updates */} 1. Connect to the [WS Market Data Pro API](/docs/ws-market-data-pro-api/introduction/) using the `wss://ws-mdpro.bitvavo.com/v2/` endpoint. 2. Subscribe to the [Book subscription channel](/docs/ws-market-data-pro-api/book-subscription/) for a market, for example **BTC-EUR**. ```json title="Book subscription message" { "action": "subscribe", "channels": [ { "name": "book", "markets": [ "BTC-EUR" ] } ] } ``` 2. You start receiving **book** events with the market data. Every event includes a range of update identified by the sequence numbers: - `startMdSeqNo`: Sequence number identifying the start of the range of events that the order book update includes. - `endMdSeqNo`: Sequence number identifying the end of the range of events that the order book update includes. ``` json title="Book update event" { "event": "book", "market": "BTC-EUR", "nonce": 438524, "bids": [ [ "9209.3", "0.015" ] ], "asks": [ ], "timestamp": 1542967486256, "startMdSeqNo": 438524, "endMdSeqNo": 438524, "type": "update" } ``` 3. Go to [step 2](#step-2-get-a-snapshot-of-the-order-book) to get a snapshot of the order book and establish the initial state of your local order book. :::caution Do not apply any updates until you’ve confirmed the correct ordering of events. ::: #### Step 2: Get a snapshot of the order book {/* #step-2-get-a-snapshot-of-the-order-book */} 1. Make a [Get order book](/docs/ws-market-data-pro-api/get-order-book/) request for that market, in this example **BTC-EUR**. ```json title="WS Market Data Pro getBook action" { "action": "getBook", "requestId": 1, "market": "BTC-EUR", "depth": 1000 } ``` The response returns: ```json title="Snapshot" { "action": "getBook", "requestId": 1, "response": { "market": "BTC-EUR", "nonce": 438525, "bids": [ [ "4999.9", "0.015" ], ... ], "asks": [ [ "5001.1", "0.015" ], ... ], "timestamp": 1542967486256, "mdSeqNo": 438525 } } ``` 2. Save the returned `mdSeqNo` from the snapshot. ```json title="Matching engine sequence number" { "mdSeqNo": 438525 } ``` You will use the `mdSeqNo` sequence number of this snapshot for the initial state of your local order book. #### Step 3: Compare the sequence numbers {/* #step-3-compare-the-sequence-numbers */} 1. After you get the [snapshot](#step-2-get-a-snapshot-of-the-order-book), compare its `mdSeqNo`,for example **438525**, with the `startMdSeqNo` of the *next* incoming **book** event from [your active subscription](#step-1-subscribe-to-order-book-updates). 2. If the `startMdSeqNo` is lower than or equal to the `mdSeqNo` of the snapshot, skip the event (it’s already included). 3. If the `startMdSeqNo` is *exactly one higher* than the snapshot `mdSeqNo`, for example **438526**, start applying the updates in order. #### Step 4: Apply the update and advance {/* #step-4-apply-the-update-and-advance */} After you've confirmed the correct ordering: 1. Update the `bids` and `asks` in your local order book to the state from each event. 2. After each update, set your local `mdSeqNo` to the `endMdSeqNo` of the last event. 3. Continue applying new event updates in sequential order. ### Troubleshoot and recover {/* #troubleshoot-and-recover */} If you detect a gap in the sequence numbers, for example, if the `startMdSeqNo` of an event is not exactly one higher than your local `mdSeqNo`: 1. Discard your local order book. 2. Re-subscribe to the [Book subscription channel](/docs/ws-market-data-pro-api/book-subscription/). 2. Get a new snapshot by making a [Get order book](/docs/ws-market-data-pro-api/get-order-book/) request and repeat the process. ### See also - [WS Market Data Pro API](/docs/ws-market-data-pro-api/) — top-level section with API actions and channel references - [Authentication](/docs/ws-market-data-pro-api/introduction/) — instructions for authenticating your WebSocket connection - [Manage order book](/docs/manage-order-book/) — practical guidance for maintaining a synchronized order book --- ## Handle errors Source: https://docs.bitvavo.com/docs/errors/ When an API request fails, Bitvavo returns an HTTP status code and a JSON body with an `errorCode` and a description. Use the `errorCode` to identify the issue and resolve it. ### Response format {/* #error-response-format */} Every error response includes an `errorCode` and an `error` message. ```json title="REST API error response" { "errorCode": 205, "error": "Invalid parameter: price" } ``` WebSocket error responses use the same fields, wrapped in an event: ```json title="WebSocket error response" { "event": "error", "errorCode": 205, "error": "Invalid parameter: price" } ``` ### HTTP 400: Bad Request {/* #http-400 */} #### Request format errors {/* #request-format */} | `errorCode` | Reason | Action | |:------------|:-------|:-------| | 102 | Your request contains invalid JSON. | Validate the JSON body before sending. | | 200 | This endpoint does not accept path parameters. | Check the [API reference](/docs/rest-api) for the correct request format. | | 201 | This endpoint does not accept body parameters. | Check the [API reference](/docs/rest-api) for the correct request format. | | 202 | This `orderType` does not support the parameter you used. | Check the [Create order](/docs/rest-api/create-order) endpoint for supported parameters. | | 203 | Your request has missing or incompatible parameters. | Check required parameters in the [API reference](/docs/rest-api). | | 204 | You used an invalid parameter for this endpoint. | Check the [API reference](/docs/rest-api) for valid parameters. | | 205 | You provided an invalid parameter value. | Check the [API reference](/docs/rest-api) for accepted values. | | 206 | You used incompatible parameters together. | Remove one of the conflicting parameters. | #### Order and trading errors {/* #order-trading */} | `errorCode` | Reason | Action | |:------------|:-------|:-------| | 210 | `amount` exceeds the maximum for this market. | Check market limits with [Get markets](/docs/rest-api/get-markets). | | 211 | `price` exceeds the maximum allowed. | Lower the `price` value. | | 212 | `amount` is below the minimum for this market. | Check `minOrderInBaseAsset` with [Get markets](/docs/rest-api/get-markets). | | 213 | `price` is too low. | Increase the `price` value. | | 215 | `price` has more than 15 decimal places. | Reduce to 15 or fewer decimal places. | | 216 | Your balance is insufficient. | Check your [account balance](/docs/rest-api/get-account-balance). | | 217 | `amountQuote` is below the minimum for this market. | Check `minOrderInQuoteAsset` with [Get markets](/docs/rest-api/get-markets). | | 219 | This market is no longer listed on Bitvavo. | Check available markets with [Get markets](/docs/rest-api/get-markets). | | 220 | A `clientOrderId` with this value already exists in the market. | Use a unique value per market. | | 231 | The market is paused and `timeInForce` is not `GTC`. | Set `timeInForce` to `GTC`. | | 232 | You did not provide any changes. | Include at least one changed parameter when [updating an order](/docs/rest-api/update-order). | | 234 | You cannot update a `market` order. | Cancel it and create a new order instead. | | 235 | You exceeded the maximum of 100 open orders per market. | Cancel existing orders before placing new ones. | | 236 | You used more than one of `amount`, `amountRemaining`, or `amountQuote`. | Use only one. | | 237 | You omitted required parameters for the `stopLoss` order type. | Check the [Create order](/docs/rest-api/create-order) endpoint for required parameters. | | 238 | You omitted required parameters for the `stopLossLimit` order type. | Check the [Create order](/docs/rest-api/create-order) endpoint for required parameters. | | 239 | You cannot switch between `amount` and `amountQuote` during an update. | Cancel the order and create a new one instead. | | 422 | The price does not align with the allowed tick size. | Get the `tickSize` for the market with [Get markets](/docs/rest-api/get-markets). | | 429 | A parameter value has too many decimal places. | Check the allowed precision for the market with [Get markets](/docs/rest-api/get-markets). | #### Market status errors {/* #market-status */} You get these errors when you interact with a market that is not in `trading` status. Check the current [market status](/docs/order-lifecycle/#market-status) with [Get markets](/docs/rest-api/get-markets). | `errorCode` | Reason | Action | |:------------|:-------|:-------| | 423 | The market is halted due to maintenance, technical issues, or other operational reasons. | Wait for the market to resume trading. | | 424 | The market is in `cancelOnly` [status](/docs/order-lifecycle/#market-status). | You can only cancel orders. | | 425 | The market is in an auction phase. | Wait for trading to resume. | | 426 | The market is in `auctionMatching` [status](/docs/order-lifecycle/#market-status). | Wait for the auction to complete. | #### Deposits and withdrawals errors {/* #deposits-withdrawals */} | `errorCode` | Reason | Action | |:------------|:-------|:-------| | 401 | This asset does not support deposits. | — | | 402 | You must verify your identity to deposit or withdraw assets. | Complete the verification process in your Bitvavo account. | | 403 | You must verify your phone number to deposit or withdraw assets. | Verify your phone number in your Bitvavo account. | | 404 | An internal error prevented the operation. | Retry the request. If the issue persists, contact [Bitvavo support](https://support.bitvavo.com/hc/en-us/articles/4405239686929-How-do-I-contact-the-support-team). | | 405 | You cannot withdraw during the cooldown period. | Wait for the cooldown to expire before retrying. | | 406 | `amount` is below the minimum allowed value. | Increase the `amount`. | | 407 | You cannot make an internal transfer for this asset. | — | | 408 | Your balance is insufficient. | Check your [account balance](/docs/rest-api/get-account-balance). | | 409 | Your bank account is not verified. | Verify your bank account and try again. | | 410 | This asset does not support withdrawals. | — | | 411 | You cannot transfer assets to yourself. | — | | 412 | The deposit or withdrawal failed. | If the issue persists, contact [Bitvavo support](https://support.bitvavo.com/hc/en-us/articles/4405239686929-How-do-I-contact-the-support-team). | | 413 | Your IP address is not in the whitelist. | Add it to your API key whitelist. | | 414 | You cannot withdraw assets within 2 minutes of logging in. | Wait and try again. | ### HTTP 403: Forbidden {/* #http-403 */} #### Authentication {/* #authentication */} | `errorCode` | Reason | Action | |:------------|:-------|:-------| | 300 | This endpoint requires authentication. | Add [authentication](/docs/rest-api/introduction/) to your request. | | 301 | Your API key has an invalid length. | Verify that you are using the correct key. | | 302 | The timestamp is not in milliseconds. | Use Unix epoch time in milliseconds for `Bitvavo-Access-Timestamp`. | | 303 | `Bitvavo-Access-Window` is out of the allowed range. | Set it to a value between 100 and 60000 milliseconds. | | 304 | Bitvavo did not receive your request within the access window. | Sync your system clock or increase `Bitvavo-Access-Window`. | | 305 | Your API key is not active. | Activate it in your Bitvavo account settings. | | 306 | You have not confirmed your API key activation. | Check the confirmation email from Bitvavo. | | 307 | Your IP is not in the whitelist for this API key. | Add your IP address to the key's whitelist. | | 308 | Your signature format is invalid. | Review the [authentication steps](/docs/rest-api/introduction/) and verify your signature generation. | | 309 | Your signature is invalid. | Verify that you sign `timestamp + method + url + body` correctly with your API secret. See [authentication](/docs/rest-api/introduction/). | #### Permissions {/* #permissions */} | `errorCode` | Reason | Action | |:------------|:-------|:-------| | 310 | Your API key does not have the **Trade digital assets** permission. | Enable it in your API key settings. | | 311 | Your API key does not have the **View access** permission. | Enable it in your API key settings. | | 312 | Your API key does not have the **Withdraw digital assets** permission. | Enable it in your API key settings. | | 313 | Your Bitvavo session is invalid. | — | | 314 | The VPC ID is invalid. | — | | 316 | This WebSocket connection only supports public asset information. | — | | 317 | Your account is locked. | Contact [Bitvavo support](https://support.bitvavo.com/hc/en-us/articles/4405239686929-How-do-I-contact-the-support-team). | | 318 | You must verify your account before using the API. | Complete verification in your Bitvavo account. | | 319 | This feature is not available in your region. | — | | 320 | Operation forbidden. | Contact [Bitvavo support](https://support.bitvavo.com/hc/en-us/articles/4405239686929-How-do-I-contact-the-support-team). | | 511 | You need the **Administrative** permission for this endpoint. | Contact [Bitvavo support](https://support.bitvavo.com/hc/en-us/articles/4405239686929-How-do-I-contact-the-support-team). | | 512 | You need the **Internal Transfer** permission for this endpoint. | Contact [Bitvavo support](https://support.bitvavo.com/hc/en-us/articles/4405239686929-How-do-I-contact-the-support-team). | | 513 | You need the **Include all subaccounts** permission for this endpoint. | Contact [Bitvavo support](https://support.bitvavo.com/hc/en-us/articles/4405239686929-How-do-I-contact-the-support-team). | | 514 | You cannot use this request for subaccount management. | — | ### HTTP 404: Not found {/* #http-404 */} | `errorCode` | Reason | Action | |:------------|:-------|:-------| | 240 | The order does not exist or is no longer active. | Check the `orderId` and ensure no conflicting calls overlap. | | 415 | Bitvavo does not recognize the WebSocket action. | Check the action name in the [WebSocket API reference](/docs/websocket-api). | | 510 | The API key is not linked to the subaccount, or the subaccount does not exist. | — | ### HTTP 409: Conflict {/* #http-409 */} | `errorCode` | Reason | Action | |:------------|:-------|:-------| | 431 | The market is in `halted`, `auction`, or `auctionMatching` [status](/docs/order-lifecycle/#market-status). | Wait for `trading` status. | ### HTTP 429: Too many requests {/* #http-429 */} | `errorCode` | Reason | Action | |:------------|:-------|:-------| | 105 | You exceeded the [rate limit](/docs/rate-limits/). Your account or IP address is temporarily blocked. | Wait until `bitvavo-ratelimit-resetat` (check the response headers) before sending new requests. | | 112 | You exceeded the WebSocket [rate limit](/docs/rate-limits/) for messages per second. | Reduce your message frequency. | ### HTTP 500: Internal server error {/* #http-500 */} | `errorCode` | Reason | Action | |:------------|:-------|:-------| | 101 | Unknown error. The service is not reachable. | Contact [Bitvavo support](https://support.bitvavo.com/hc/en-us/articles/4405239686929-How-do-I-contact-the-support-team). | | 400 | Unknown server error. | Contact [Bitvavo support](https://support.bitvavo.com/hc/en-us/articles/4405239686929-How-do-I-contact-the-support-team). | ### HTTP 503: Service unavailable {/* #http-503 */} | `errorCode` | Reason | Action | |:------------|:-------|:-------| | 107 | Bitvavo is overloaded. | Retry after 500 ms. | | 108 | Bitvavo encountered a processing issue. | Increase your `Bitvavo-Access-Window` or retry after 500 ms. | | 109 | The request timed out. The operation may or may not have succeeded. | Check the state before retrying to avoid duplicates (for example, [get the order](/docs/rest-api/get-order) before creating it again). | | 111 | The matching engine is temporarily unavailable. | Retry after a short delay. | | 419 | The server is unavailable. | Retry after a short delay. | | 430 | The connection timed out because Bitvavo received no new market data events. | Check that the market is in `trading` [status](/docs/order-lifecycle/#market-status). | ### Handle retries {/* #retry-guidelines */} | HTTP status | Retry? | Guidance | |:------------|:-------|:---------| | 400 | No | Fix your request. Check parameters, values, and formats. | | 403 | No | Fix authentication or permissions. Check your API key, signature, and key settings. | | 404 | No | Fix the resource reference (for example, `orderId` or WebSocket action name). | | 409 | Wait | The market is not in `trading` status. Wait for the [market status](/docs/order-lifecycle/#market-status) to change. | | 429 | Yes, after delay | Wait until `bitvavo-ratelimit-resetat` before retrying. See [rate limits](/docs/rate-limits/). | | 500 | Yes, after increasing delay | Retry after 500 ms, then 1 s, then 2 s, and so on. If the error persists, contact [Bitvavo support](https://support.bitvavo.com/hc/en-us/articles/4405239686929-How-do-I-contact-the-support-team). | | 503 | Yes, after short delay | Retry after 500 ms. For `errorCode` 109, verify the operation state before retrying. | :::tip For `errorCode` 109 (timeout), the operation may have already succeeded. Always check the current state (for example, [get the order](/docs/rest-api/get-order)) before retrying to avoid duplicates. ::: ### See also - [Rate limits](/docs/rate-limits/) — weight point limits, headers, and block durations - [Authentication](/docs/rest-api/introduction/) — sign REST API requests - [WebSocket authentication](/docs/websocket-api/introduction/) — authenticate WebSocket connections - [Order lifecycle](/docs/order-lifecycle/) — order types, statuses, and cancellation reasons - [Cancel on disconnect](/docs/cancel-on-disconnect/) — automatic order cancellation on connection loss --- ## Rate limits Source: https://docs.bitvavo.com/docs/rate-limits/ There are limits to the number of API requests that you can make within one minute. Every request to a REST endpoint or a WebSocket action is allocated a number of *Rate limit weight points*. For example, a [Create order](/docs/rest-api/create-order) request uses **1** weight point. #### How it's calculated The system tracks the number of weight points you use within one minute. The default rate limit is **1000** weight points per minute. Every minute the system resets the counter at `bitvavo-ratelimit-resetat`. For every request to Bitvavo API, both REST and WebSocket, the weight points within a minute are subtracted from `bitvavo-ratelimit-limit`. The system calculates the `bitvavo-ratelimit-remaining` weight points before the next `bitvavo-ratelimit-resetat`. For the calculation, there is also a difference between authenticated and unauthenticated users: - If you authenticate your requests, we track your rate limit based on your API key. This applies to both the public and private endpoints. - If you don't authenticate your requests, we track your rate limit based on your IP address. This only applies to the public endpoints. #### Going over the limit If you exceed `bitvavo-ratelimit-limit` within one minute: - *Authenticated users* are blocked for **1 minute** (tracked by API key). - *Unauthenticated users* are blocked for **15 minutes** (tracked by IP address). This results in an [HTTP 429 response](/docs/errors#http-429) with `errorCode` **105**. For example, if you exceed the rate limit at 12:00:15 as an authenticated user, you will be able to make requests again at 12:02:00. This is because you used up the rate limit for that first minute and the system blocks you for another minute. #### Retrieve the remaining weight points Rate limit details are included in the REST API response 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`. For requests to the WebSocket API, the response doesn't include the rate limit headers. To keep track of your weight points, you need to make a request to the REST API. #### WebSocket request throttling You can have multiple WebSockets sessions at the same time. Each WebSocket session has a limit of 5000 messages per one second. If you exceed this limit, you get an [HTTP 429](/docs/errors#http-429) error with an `errorCode` **112**. #### WebSocket Market Data Pro request throttling You can have multiple Market Data Pro sessions at the same time. However, currently each session has a limit of 50 messages per one second. If you exceed this limit, you get an [HTTP 429](/docs/errors#http-429) error with an `errorCode` **112**. --- ## Release management Source: https://docs.bitvavo.com/docs/release-management/ Bitvavo releases API changes in a predictable and structured way so you can plan, test, and deploy updates without unexpected impact. Bitvavo uses [semantic versioning](https://semver.org/) for public APIs. This section explains how Bitvavo classifies API changes, versions them, and communicates upcoming releases. ### Types of changes Bitvavo uses three types of API changes: an internal change, an external change, or a breaking change. #### Internal changes Internal changes do not affect API behavior that you can observe or rely on. These changes include internal technical improvements and bug fixes that do not alter requests, responses, or event flows. You do not need to take any action for internal changes. #### External changes External changes are visible to you but remain backward compatible. If you do not adopt the change, your integration continues to work as before. These changes include adding new endpoints or messages, adding optional parameters, adding new enum values, or changing the ordering of fields. External changes can result in a minor or a patch version update. #### Breaking changes Breaking changes require action from you. If you do not update your integration, requests may fail or return incorrect results. These changes include removing or renaming endpoints, removing parameters, adding mandatory parameters, changing data types, changing request or response structures, altering event flow, or changing authentication mechanisms. Breaking changes result in a major version update. ### Communication and timelines We use our [Releases changelog](/releases/) section to communicate upcoming changes ahead of a release. For external changes to the APIs, we strive towards having the sneak preview updated between two and four weeks before the release. This gives you time to prepare, test, and migrate when required. ### See also - [Releases changelog](/releases/) --- ## Introduction Source: https://docs.bitvavo.com/docs/rest-api/introduction/ Trading, market data, transfers, and account management using request-response messaging over HTTP. For the complete OpenAPI reference, see the Exchange REST API specs. ### Headers To authenticate requests, you need to add a [signature](#create-a-signature) with the following HTTP headers in every request to Bitvavo REST API: - `Bitvavo-Access-Key` (*required*): an [API Key](https://account.bitvavo.com/user/api) with the required [permissions](#permissions). - `Bitvavo-Access-Timestamp` (*required*): a Unix timestamp in milliseconds of the time you make the request. - `Bitvavo-Access-Signature` (*required*): a [HMAC-SHA256 hex-encoded string](#create-a-signature) of the following values: - `secret`: the API secret for your `Bitvavo-Access-Key`. - `timestamp`: the same Unix timestamp as for `Bitvavo-Access-Timestamp`. - `method`: the HTTP method of the request. For example, **GET** or **POST**. - `path`: the API path of the request. For example, `/v2/order`. - `body`: for the **GET** `method`, an empty string. For every other `method`, the request body as a string. - `Bitvavo-Access-Window` (*optional*): the execution timeout in milliseconds after `Bitvavo-Access-Timestamp`. The default value is **10000**, and the maximum value is **60000**. ### Create a signature To create the HMAC-SHA256 hex-encoded `Bitvavo-Access-Signature`: 1. Prepare the header values. For example: - `timestamp`: **1548172481125** - `method`: **POST** - `path`: **/v2/order** - `body` (*optional*): **`{"market":"BTC-EUR","side":"buy","price":"5000","amount":"1.23","orderType":"limit"}`** 2. Concatenate the values without a delimiter: ```text title="Concatenated string" 1548172481125POST/v2/order{"market":"BTC-EUR","side":"buy","price":"5000","amount":"1.23","orderType":"limit"} ``` 3. Prepare the API `secret` for your `Bitvavo-Access-Key`. For example: ```text title="Example API secret" bitvavo ``` 4. Using your API `secret`, encode the concatenated string to HMAC-SHA256: ```text title="Signature encoded with the Example API secret" 44d022723a20973a18f7ee97398b9fdd405d2d019c8d39e24b8cc0dcb39ca016 ``` #### Python example Below is a Python code sample on how to sign a [Create order](/docs/rest-api/create-order) request: ```python title="Sign a create order request" 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 REST API. :param endpoint: the API endpoint to which you make the request. For example, `/order`. :param body: for the GET method, an empty string. For every other method, the request body as a string. :param method: the HTTP method of the request. For example, `GET` or `POST`. """ now = int(time.time() * 1000) body = json.dumps(body, separators=(',', ':')) if body else '' 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), 'Content-Type': 'application/json', } r = requests.request(method=method, url=url, headers=headers, data=body) return r.json() def create_signature(self, timestamp: int, method: str, url: str, body: str): """ Create an HMAC-SHA256 hex-encoded signature to authenticate requests to Bitvavo REST API. :param timestamp: a Unix timestamp in milliseconds of the time you make the request. :param method: the HTTP method of the request. For example, `GET` or `POST`. :param url: the API endpoint to which you make the request. For example, `/order`. :param body: for the GET method, an empty string. For every other method, the request body as a string. """ string = str(timestamp) + method + '/v2' + url + body signature = hmac.new(self.api_secret.encode('utf-8'), string.encode('utf-8'), hashlib.sha256).hexdigest() return signature ``` #### JavaScript example Below is a JavaScript example on how to sign a request to the Bitvavo REST API from Node.js: ```javascript title="Sign a request using JavaScript (Node.js)" const crypto = require('crypto'); const apiKey = 'YOUR_API_KEY'; const apiSecret = 'YOUR_API_SECRET'; const accessWindow = 10000; const method = 'POST'; const endpoint = '/v2/order'; const url = 'https://api.bitvavo.com' + endpoint; // For GET requests, use an empty string const bodyObject = { market: 'BTC-EUR', side: 'buy', orderType: 'limit', amount: '0.1', price: '50000' }; // Ensure the body string used for signing is identical to the body sent in the request const body = method === 'GET' ? '' : JSON.stringify(bodyObject); // Timestamp in milliseconds const timestamp = Date.now().toString(); // Concatenated string: timestamp + method + path + body const payload = `${timestamp}${method}${endpoint}${body}`; // HMAC-SHA256 signature as a hex-encoded string const signature = crypto .createHmac('sha256', apiSecret) .update(payload) .digest('hex'); // Headers const headers = { 'Bitvavo-Access-Key': apiKey, 'Bitvavo-Access-Signature': signature, 'Bitvavo-Access-Timestamp': timestamp, 'Bitvavo-Access-Window': accessWindow.toString(), 'Content-Type': 'application/json', }; // Example request using fetch (Node 18+) fetch(url, { method, headers, body: method === 'GET' ? undefined : body, }) .then((res) => res.json()) .then(console.log) .catch(console.error); ``` #### Testing from Postman To authenticate requests to private endpoints in the official [Bitvavo Postman collection](https://www.postman.com/bitvavo/bitvavo-api/overview), set the following collection variables: - `bitvavo_api_key` - `bitvavo_api_secret` - `bitvavo_access_window` (optional, default: `10000`) The collection includes a pre-request script that automatically signs private requests. Public endpoints can be used without credentials. ### Permissions To control the actions your app can execute, you add permissions to your [API key](https://account.bitvavo.com/user/api) in your [Bitvavo dashboard](https://account.bitvavo.com/user/api). You can enable: - **Read-only**: retrieve information about your account and transfers. To retrieve order and trade information, your API key must also have the **Trade digital assets** permission. - **Trade digital assets**: place, update, view, and cancel orders. To retrieve 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 a verified bank account. :::warning Withdrawals made using Bitvavo API **do not** require 2FA and e-mail confirmation. ::: --- ## Get order book Source: https://docs.bitvavo.com/docs/rest-api/get-order-book/ `GET` `/{market}/book` Returns the list of up to 1000 bids and asks per request for the specified `market`, sorted by `price`. :::info This is a *public* endpoint. However, [authenticating](/docs/rest-api/introduction/) your request gives you a [higher rate limit](/docs/rate-limits/#how-its-calculated). ::: **Rate limit weight points**: 1 ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | path | yes | The market for which to return the order book. | | `depth` | query | no | The number of `bids` and `asks` to return. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo() response = bitvavo.book('BTC-EUR', {}) for item in response['bids']: print('Bids', item) for item in response['asks']: print('Asks', item) ``` --- ## Get order book report Source: https://docs.bitvavo.com/docs/rest-api/get-order-book-report/ `GET` `/report/{market}/book` Returns the list of up to 1000 bids and asks for the specified `market`, sorted by `price`. Includes the data compliant with the European Markets in Crypto-Assets (MiCA) regulation. :::info This is a *public* endpoint. However, [authenticating](/docs/rest-api/introduction/) your request gives you a [higher rate limit](/docs/rate-limits/#how-its-calculated). ::: **Rate limit weight points**: 1 ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | path | yes | The market for which to return the order book. | | `depth` | query | no | The number of `bids` and `asks` to return. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo() response = bitvavo.book('BTC-EUR', {}) for item in response['bids']: print('Bids', item) for item in response['asks']: print('Asks', item) ``` --- ## Get trades Source: https://docs.bitvavo.com/docs/rest-api/get-trades/ `GET` `/{market}/trades` Returns the list of trades made by all Bitvavo users for the specified `market` and time period up to 24 hours. The returned trades are sorted by their `timestamp` in a descending order, from the latest to the earliest. :::info This is a *public* endpoint. However, [authenticating](/docs/rest-api/introduction/) your request gives you a [higher rate limit](/docs/rate-limits/#how-its-calculated). ::: :::tip To get the list of your past trades, make a [Get trades history](/docs/rest-api/get-trades) request. ::: **Rate limit weight points**: 5 ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | path | yes | The market for which to return the trades. | | `limit` | query | no | The maximum number of trades to return. | | `start` | query | no | The Unix timestamp starting from which to return trades.
> Can only return trades for a period of up to 24 hours. | | `end` | query | no | The Unix timestamp until which to return trades.
> Cannot be more than 24 hours after the `start` parameter. Can only return trades for a period of up to 24 hours. | | `tradeIdFrom` | query | no | The unique identifier of the trade starting from which to return the trades. | | `tradeIdTo` | query | no | The unique identifier of the trade up to which to return the trades. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo() response = bitvavo.publicTrades('BTC-EUR', {}) for trade in response: print(trade) ``` --- ## Get trades report Source: https://docs.bitvavo.com/docs/rest-api/get-trades-report/ `GET` `/report/{market}/trades` Returns the list of trades from for the specified `market` and time period made by all Bitvavo users. The returned trades are sorted by their `timestamp` in a descending order, from the latest to the earliest. Includes the data compliant with the European Markets in Crypto-Assets (MiCA) regulation. :::info This is a *public* endpoint. However, [authenticating](/docs/rest-api/introduction/) your request gives you a [higher rate limit](/docs/rate-limits/#how-its-calculated). ::: **Rate limit weight points**: 5 ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | path | yes | The market for which to return the trades. | | `limit` | query | no | The maximum number of trades to return. | | `start` | query | no | The Unix timestamp starting from which to return trades.
> Can only return trades for a period of up to 24 hours. | | `end` | query | no | The Unix timestamp until which to return trades.
> Cannot be more than 24 hours after the `start` parameter. Can only return trades for a period of up to 24 hours. | | `tradeIdFrom` | query | no | The unique identifier of the trade starting from which to return the trades. | | `tradeIdTo` | query | no | The unique identifier of the trade up to which to return the trades. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo() response = bitvavo.publicTrades('BTC-EUR', {}) for trade in response: print(trade) ``` --- ## Get ticker prices Source: https://docs.bitvavo.com/docs/rest-api/get-ticker-prices/ `GET` `/ticker/price` Returns prices of the latest trades on Bitvavo for all markets or a single `market`. :::info This is a *public* endpoint. However, [authenticating](/docs/rest-api/introduction/) your request gives you a [higher rate limit](/docs/rate-limits/#how-its-calculated). ::: :::note A _tick_ in a market is any change in the price of a digital asset. ::: **Rate limit weight points**: 1 ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | query | no | The market for which to return the latest information. > For the list of all markets on Bitvavo, make a [Get markets](/docs/rest-api/get-markets) request. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo() response = bitvavo.tickerPrice({}) for market in response: print(market) ``` --- ## Get ticker book Source: https://docs.bitvavo.com/docs/rest-api/get-ticker-book/ `GET` `/ticker/book` Returns the highest buy and the lowest sell prices currently available for all markets, or a single `market`, in the Bitvavo order book. :::info This is a *public* endpoint. However, [authenticating](/docs/rest-api/introduction/) your request gives you a [higher rate limit](/docs/rate-limits/#how-its-calculated). ::: **Rate limit weight points**: 1 ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | query | no | The market for which to return the latest information. > For the list of all markets on Bitvavo, make a [Get markets](/docs/rest-api/get-markets) request. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo() response = bitvavo.tickerBook({}) for market in response: print(market) ``` --- ## Get candlestick data Source: https://docs.bitvavo.com/docs/rest-api/get-candlestick-data/ `GET` `/{market}/candles` Returns the [OHLCV](https://www.investopedia.com/terms/o/ohlcchart.asp) market data used to create [candlestick charts](https://learn.bitvavo.com/article/what-are-candlestick-patterns/1199). Candlestick data is always returned in chronological order from the latest to the earliest. Data is returned when trades are made in the `interval` represented by that candlestick. If no trades occur you see a gap in data flow - zero trades are represented by zero candlesticks. :::info This is a *public* endpoint. However, [authenticating](/docs/rest-api/introduction/) your request gives you a [higher rate limit](/docs/rate-limits/#how-its-calculated). ::: **Rate limit weight points**: 1 ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | path | yes | The market for which to return the candlestick data. > For the list of all markets on Bitvavo, make a [Get markets](/docs/rest-api/get-markets) request. | | `interval` | query | yes | The time interval between each candlestick. Determines the allowed values for `start` and `end` parameters. | | `limit` | query | no | The maximum number of candlestick data to return. | | `start` | query | no | The Unix timestamp starting from which to return the candlestick data.
> The timestamp must align exactly with the start of the specified `interval`. For example, for a 1-hour candlestick that starts at 13:00:00.000 Amsterdam time, use `1704067200000`. | | `end` | query | no | The Unix timestamp until which to return the candlestick data.
> The timestamp must align exactly with the end of the specified `interval`. For example, for a 1-hour candlestick that ends at 14:00:00.000 Amsterdam time, use `1766062800000`. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo from datetime import datetime, timezone bitvavo = Bitvavo() # Query the last 1440 one hour candles of the BTC-EUR market candles = bitvavo.candles('BTC-EUR', '1h') for (ts, o, h, l, c, v) in candles: print('Timestamp', ts, 'open', o, 'high', h, 'low', l, 'close', c, 'volume', v) # Limit the result to 10 values candles = bitvavo.candles('BTC-EUR', '1h', limit=10) for (ts, o, h, l, c, v) in candles: print('Timestamp', ts, 'open', o, 'high', h, 'low', l, 'close', c, 'volume', v) # Specify a date range start = datetime(year=2024, month=1, day=1, hour=0, minute=0, tzinfo=timezone.utc) end = datetime(year=2024, month=1, day=1, hour=1, minute=0, tzinfo=timezone.utc) candles = bitvavo.candles('BTC-EUR', '15m', start=start, end=end) for (ts, o, h, l, c, v) in candles: print('Timestamp', ts, 'open', o, 'high', h, 'low', l, 'close', c, 'volume', v) # Before 1.3.2 candles = bitvavo.candles('BTC-EUR', '1h', {}) for candle in candles: print('Timestamp', candle[0], ' open', candle[1], ' high', candle[2], ' low', candle[3], ' close', candle[4], ' volume', candle[5]) ``` --- ## Get ticker data 24h Source: https://docs.bitvavo.com/docs/rest-api/get-ticker-data-24-h/ `GET` `/ticker/24h` Returns the [OHLCV](https://www.investopedia.com/terms/o/ohlcchart.asp) data about trades and orders for all markets, or a single `market`, on Bitvavo during the latest 24 hours. :::info This is a *public* endpoint. However, [authenticating](/docs/rest-api/introduction/) your request gives you a [higher rate limit](/docs/rate-limits/#how-its-calculated). ::: **Rate limit weight points**: **25** (without `market`) or **1** (with `market`). ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | query | no | The market for which to return the latest information. > For the list of all markets on Bitvavo, make a [Get markets](/docs/rest-api/get-markets) request. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo() response = bitvavo.ticker24h({}) for market in response: print(market) ``` --- ## Create order Source: https://docs.bitvavo.com/docs/rest-api/create-order/ `POST` `/order` Creates an order to buy or sell digital assets on Bitvavo. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: :::warning You can have a maximum of [100 open orders](/docs/rest-api/get-orders) at any one time in each `market`. :::: **Rate limit weight points**: **1** ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo({ 'APIKEY': '', 'APISECRET': '' }) response = bitvavo.placeOrder('BTC-EUR', 'sell', 'limit', { 'amount': '0.1', 'price': '5000', 'operatorId': 543462 }) print(response) ``` --- ## Update order Source: https://docs.bitvavo.com/docs/rest-api/update-order/ `PUT` `/order` Updates an existing *limit* or *trigger* order. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: :::info You must set either `orderId` or `clientOrderId`. If you set both, we use the `clientOrderId` to identify the order. `clientOrderId` is only returned if you set it when you created the order. ::: :::tip Updating an order is faster than canceling and creating new orders. During the update, your order is briefly removed from the order book. ::: **Rate limit weight points**: 1.
### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo({ 'APIKEY': '', 'APISECRET': '' }) response = bitvavo.updateOrder('BTC-EUR', 'a4a5d310-687c-486e-a3eb-1df832405ccd', { 'amount': '1.1', 'operatorId': 543462 }) print(response) ``` --- ## Get order Source: https://docs.bitvavo.com/docs/rest-api/get-order/ `GET` `/order` Returns information about an existing order. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: :::info You must set either `orderId` or `clientOrderId`. If you set both, we use the `clientOrderId` to identify the order. `clientOrderId` is only returned if you set it when you created the order. ::: **Rate limit weight points**: **1** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | query | yes | The market in which order was made. | | `orderId` | query | yes | Bitvavo identifier of the order. | | `clientOrderId` | query | no | Your identifier of the order.
> If both `clientOrderId` and `orderId` are set, we use the `clientOrderId` to identify the order. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo({ 'APIKEY': '', 'APISECRET': '' }) response = bitvavo.getOrder('XRP-BTC', 'a4a5d310-687c-486e-a3eb-1df832405ccd') print(response) ``` --- ## Cancel order Source: https://docs.bitvavo.com/docs/rest-api/cancel-order/ `DELETE` `/order` Cancels an open order. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: :::info You must set either `orderId` or `clientOrderId`. If you set both, we use the `clientOrderId` to identify the order. `clientOrderId` is only returned if you set it when you created the order. ::: **Rate limit weight points**: **1** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | query | yes | The market in which order was made. | | `orderId` | query | yes | Bitvavo identifier of the order. | | `operatorId` | query | yes | Your identifier for the trader or the bot within your account that made the request. | | `clientOrderId` | query | no | Your identifier of the order.
> If both `clientOrderId` and `orderId` are set, we use the `clientOrderId` to identify the order. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo({ 'APIKEY': '', 'APISECRET': '' }) response = bitvavo.cancelOrder('BTC-EUR', 'a4a5d310-687c-486e-a3eb-1df832405ccd', { 'operatorId': 543462 }) print('Deleted', response['orderId']) ``` --- ## Get open orders Source: https://docs.bitvavo.com/docs/rest-api/get-open-orders/ `GET` `/ordersOpen` Returns all current open orders. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: **Rate limit weight points**: **100** (without `market`) or **5** (with `market`). ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | query | no | The market in which to return the open orders. If not specified, all open orders are returned. | | `base` | query | no | The base asset for which to return the open orders. If neither `market` nor `base` are specified, all open orders are returned. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo({ 'APIKEY': '', 'APISECRET': '' }) response = bitvavo.ordersOpen({}) for item in response: print(item) ``` --- ## Get trade history Source: https://docs.bitvavo.com/docs/rest-api/get-trade-history/ `GET` `/trades` Returns the specified number of past trades for your account and a time period of up to 24 hours. Does not return trades with a Price Guarantee. The returned trades are sorted by their `timestamp` in a descending order, from the latest to the earliest. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: :::tip To get a specific list of trades, use the `start`, `end`, `tradeIdFrom`, and `tradeIdTo` parameters. :::: :::tip To get all past transactions for your account, use the [Get transaction history](/docs/rest-api/get-transaction-history/) request. :::: **Rate limit weight points**: **5** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | query | yes | The market for which to return the past trades. | | `limit` | query | no | The maximum number of trades to return, from latest to earliest. | | `start` | query | no | The Unix timestamp starting from which to return trades.
> Can only return trades for a period of up to 24 hours. | | `end` | query | no | The Unix timestamp up to which to return trades.
> Cannot be more than 24 hours after the `start` parameter. Can only return trades for a period of up to 24 hours. | | `tradeIdFrom` | query | no | The unique identifier of the trade starting from which to return the trades. | | `tradeIdTo` | query | no | The unique identifier of the trade up to which to return the trades. | | `tradeId` | query | no | **Deprecated**: `tradeId` is interpreted as `tradeIdTo`. If used, returns all trades up to this `tradeId`. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo({ 'APIKEY': '', 'APISECRET': '' }) response = bitvavo.trades('BTC-EUR', {}) for item in response: print(item) ``` --- ## Get orders Source: https://docs.bitvavo.com/docs/rest-api/get-orders/ `GET` `/orders` Returns information about multiple orders. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: **Rate limit weight points**: **5** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | query | yes | The market in which to get the order. | | `limit` | query | no | The maximum number of orders to return, from latest to earliest. | | `start` | query | no | The Unix timestamp starting from which to return orders. | | `end` | query | no | The Unix timestamp up to which to return orders. | | `orderIdFrom` | query | no | The unique identifier of the order starting from which to return the orders. | | `orderIdTo` | query | no | The unique identifier of the order up to which to return the orders. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo({ 'APIKEY': '', 'APISECRET': '' }) response = bitvavo.getOrders('BTC-EUR', {}) for item in response: print(item) ``` --- ## Cancel orders Source: https://docs.bitvavo.com/docs/rest-api/cancel-orders/ `DELETE` `/orders` Cancels multiple orders for the specified market or the account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: **Rate limit weight points**: **100** (without `market`) or **25** (with `market`). ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | query | no | The market in which to cancel the orders.
If not specified, all open orders are canceled. | | `operatorId` | query | yes | Your identifier for the trader or the bot within your account that made the request. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo({ 'APIKEY': '', 'APISECRET': '' }) response = bitvavo.cancelOrders({'BTC-EUR', 'operatorId': '543462'}) for item in response: print(item) ``` --- ## Atomic cancel orders Source: https://docs.bitvavo.com/docs/rest-api/atomic-cancel-orders/ `DELETE` `/atomic/orders` Cancels all open orders to buy or sell in the specified `market` as a single atomic request. The request is processed in strict arrival order and executed without interleaving with other operations. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: **Rate limit weight points**: **100** --- ## Cancel orders after Source: https://docs.bitvavo.com/docs/rest-api/cancel-orders-after/ `POST` `/cancelOrdersAfter` Creates an identifier used to group open orders and sets the countdown timer after which those orders are automatically canceled. To learn how to use this endpoint, see [Cancel on disconnect](/docs/cancel-on-disconnect/). :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: :::info 💡You can create only one group. If you need to create multiple groups, reach out to your Bitvavo contact to enable this. ::: **Rate limit weight points**: **5** --- ## Get deposit data Source: https://docs.bitvavo.com/docs/rest-api/get-deposit-data/ `GET` `/deposit` Returns wallet or bank account information required to deposit digital or fiat assets. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: **Rate limit weight points**: **1** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `symbol` | query | yes | The asset you want to deposit. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo({ 'APIKEY': '', 'APISECRET': '' }) response = bitvavo.depositAssets('BTC') print(response) ``` --- ## Get deposit history Source: https://docs.bitvavo.com/docs/rest-api/get-deposit-history/ `GET` `/depositHistory` Returns all past deposits for your account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: **Rate limit weight points**: **5** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `symbol` | query | no | The asset for which to return the deposit history. If not specified, all deposits are returned. | | `limit` | query | no | The maximum number of deposits to return, from latest to earliest. | | `start` | query | no | The Unix timestamp starting from which to return deposits. | | `end` | query | no | The Unix timestamp up to which to return deposits. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo({ 'APIKEY': '', 'APISECRET': '' }) response = bitvavo.depositHistory({}) for item in response: print(item) ``` --- ## Withdraw assets Source: https://docs.bitvavo.com/docs/rest-api/withdraw-assets/ `POST` `/withdrawal` Request to withdraw assets to a wallet or bank account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: :::warning 2FA and address confirmation by email are disabled for withdrawals using the API. ::: **Rate limit weight points**: **1** ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo({ 'APIKEY': '', 'APISECRET': '' }) response = bitvavo.withdrawAssets('BTC', '1', 'BitcoinAddress', {}) print(response) ``` --- ## Withdraw crypto assets Source: https://docs.bitvavo.com/docs/rest-api/withdraw-crypto-assets/ `POST` `/crypto/withdrawal` Request to withdraw crypto assets to a wallet over the specified network. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: **Rate limit weight points**: **25** --- ## Get withdrawal history Source: https://docs.bitvavo.com/docs/rest-api/get-withdrawal-history/ `GET` `/withdrawalHistory` Returns all past withdrawals for your account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: **Rate limit weight points**: **5** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `symbol` | query | no | The asset for which you want to retrieve past withdrawals. If not specified, all withdrawals are returned. | | `limit` | query | no | The maximum number of withdrawals to return, from latest to earliest. | | `start` | query | no | The Unix timestamp starting from which to return withdrawals. | | `end` | query | no | The Unix timestamp up to which to return withdrawals. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo({ 'APIKEY': '', 'APISECRET': '' }) response = bitvavo.withdrawalHistory({}) for item in response: print(item) ``` --- ## Get account fees Source: https://docs.bitvavo.com/docs/rest-api/get-account-fees/ `GET` `/account` Returns your current trading fees from the default [Category A](https://bitvavo.com/en/fees) based on the trading volume of your account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: **Rate limit weight points**: **1** ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo({ 'APIKEY': '', 'APISECRET': '' }) response = bitvavo.account() print(response) ``` --- ## Get account balance Source: https://docs.bitvavo.com/docs/rest-api/get-account-balance/ `GET` `/balance` Returns the current balance for your account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: **Rate limit weight points**: **5** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `symbol` | query | no | The asset for which you want to return the balance. If not specified, returns the balance for all assets above zero. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo({ 'APIKEY': '', 'APISECRET': '' }) response = bitvavo.balance({}) for item in response: print(item) ``` --- ## Get staking balance Source: https://docs.bitvavo.com/docs/rest-api/get-staking-balance/ `GET` `/stakingBalance` Returns the amount of crypto assets in your account that are currently in [fixed staking positions](https://support.bitvavo.com/hc/en-us/articles/4405243949841-Staking-at-Bitvavo) and are not available for trading. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: :::tip This request only returns assets locked in fixed staking. To get your balance available for trading, use the [Get account balance](/docs/rest-api/get-account-balance/) request. ::: **Rate limit weight points**: **5** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `symbol` | query | no | The asset for which you want to return the staking balance. If not specified, returns the staking balance for all assets above zero. | --- ## Get market fees Source: https://docs.bitvavo.com/docs/rest-api/get-market-fees/ `GET` `/account/fees` Returns your current trading fees from the [Category](https://bitvavo.com/en/fees) of the specified market based on the trading volume of your account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: **Rate limit weight points**: **1** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | query | no | The market for which to get fee information. If not specified, returns the fees for your current tier in [Category A](https://bitvavo.com/en/fees). | | `quote` | query | no | The quote currency for which to get fee information. If not specified, returns the fees for your current tier in [Category A](https://bitvavo.com/en/fees). | --- ## Get transaction history Source: https://docs.bitvavo.com/docs/rest-api/get-transaction-history/ `GET` `/account/history` Returns a list of past transactions for your account or the specified date range. If the range is not specified, returns all past transactions. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/rest-api/introduction/). ::: **Rate limit weight points**: **1** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `fromDate` | query | no | The Unix timestamp starting from which to return transactions. | | `toDate` | query | no | The Unix timestamp up to which to return transactions. | | `page` | query | no | The page number for the transaction history. | | `maxItems` | query | no | The maximum number of items per page in the transaction history. | | `type` | query | no | The type of transaction to return. | --- ## Get server time Source: https://docs.bitvavo.com/docs/rest-api/get-server-time/ `GET` `/time` Returns the current Unix timestamp of Bitvavo servers. :::info This is a *public* endpoint. However, [authenticating](/docs/rest-api/introduction/) your request gives you a [higher rate limit](/docs/rate-limits/#how-its-calculated). ::: **Rate limit weight points**: **1** ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo() response = bitvavo.time() print('Current time:', response['time']) ``` --- ## Get markets Source: https://docs.bitvavo.com/docs/rest-api/get-markets/ `GET` `/markets` Returns the information about one or all markets on Bitvavo. :::info This is a *public* endpoint. However, [authenticating](/docs/rest-api/introduction/) your request gives you a [higher rate limit](/docs/rate-limits/#how-its-calculated). ::: **Rate limit weight points**: **1** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `market` | query | no | The market for which to return information. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo() response = bitvavo.markets({}) for market in response: print(market) ``` --- ## Get asset data Source: https://docs.bitvavo.com/docs/rest-api/get-asset-data/ `GET` `/assets` Returns the information about the specified assets. :::info This is a *public* endpoint. However, [authenticating](/docs/rest-api/introduction/) your request gives you a [higher rate limit](/docs/rate-limits/#how-its-calculated). ::: **Rate limit weight points**: **1** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `symbol` | query | no | The asset for which to return the information. If not specified, all supported assets are returned. | ### Python example ```python from python_bitvavo_api.bitvavo import Bitvavo bitvavo = Bitvavo() response = bitvavo.assets({}) for asset in response: print(asset) ``` --- ## Introduction Source: https://docs.bitvavo.com/docs/websocket-api/introduction/ Real-time WebSocket API for market data, trading, transfers, and account management on Bitvavo. :::info Exchange WebSocket API requires authentication for operations related to trading, transfers, or account management. ::: For the complete AsyncAPI reference, see the Exchange WebSocket API specs. ### Authentication For messages that require authentication, you must first send a message to authenticate your WebSocket connection. After the connection is authenticated, you can start sending messages to the WebSocket API. To do this, you need to: 1. Create a [signature](#create-a-signature). 2. Send an [action to authenticate](#step-2-send-an-action-to-authenticate) your connection. #### Step 1: Create a signature {/* #create-a-signature */} You first need to create an HMAC-SHA256 hex-encoded `signature`: 1. Prepare the parameter values: - `timestamp`: **1548175200641** - `method`: **GET** - `path`: **/v2/websocket** - `body`: do *not* include a body. 2. Concatenate the values without a delimiter: ```text title="Concatenated string" 1548175200641GET/v2/websocket ``` 3. Prepare the API `secret` for your `Bitvavo-Access-Key`. For example: ```text title="API secret" bitvavo ``` 4. Encode the concatenated string to HMAC-SHA256 using the API `secret` for your API `key`. You get: ```text title="Signature" 653fc0505431c63a043273da4bd2f0927eae83948d796084f313e5d1131b0d6f ``` #### Step 2: Send an action to authenticate {/* #step-2-send-an-action-to-authenticate */} Now that you have created a signature, to authenticate your connection to the WebSocket API: 1. Connect to `wss://ws.bitvavo.com/v2/` 2. Create a JSON object with: - `action`: **authenticate** - `key`: **YOUR_API_KEY** - `signature`: the [signature](#create-a-signature) you created. - `timestamp`: the Unix timestamp in milliseconds of the time you make the request. - `window` (*optional*): the time in milliseconds in which your request is allowed to execute. The default value is **10000**, and the maximum value is **60000**. 3. Send the message to the WebSocket API: ```json title="Authenticate message" { "action": "authenticate", "key": "YOUR_API_KEY", "signature": "653fc0505431c63a043273da4bd2f0927eae83948d796084f313e5d1131b0d6f", "timestamp": 1548175200641 } ``` 4. Your connection is now authenticated, and you can start sending messages to the WebSocket API. ### Python example The following Python code sample shows how to sign [authenticate](#step-2-send-an-action-to-authenticate) message. To learn more, see our [Python SDK](https://github.com/bitvavo/python-bitvavo-api). ```python title="Authenticate message" 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)) ``` ### Permissions To control the actions your app can execute, you add permissions to your [API key](https://account.bitvavo.com/user/api) in your [Bitvavo dashboard](https://account.bitvavo.com/user/api). You can enable: - **Read-only**: retrieve information about your account and transfers. To retrieve order and trade information, your API key must also have the **Trade digital assets** permission. - **Trade digital assets**: place, update, view, and cancel orders. To retrieve 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 a verified bank account. :::warning Withdrawals made using Bitvavo API **do not** require 2FA and e-mail confirmation. ::: --- ## Get order book Source: https://docs.bitvavo.com/docs/websocket-api/get-order-book/ Returns the list of up to 1000 bids and asks per request for the specified `market`, sorted by `price`. **Rate limit weight points**: 1 --- ## Get trades Source: https://docs.bitvavo.com/docs/websocket-api/get-trades/ Returns the list of trades made by all Bitvavo users for the specified `market` and time period up to 24 hours. The returned trades are sorted by their `timestamp` in a descending order, from the latest to the earliest. **Rate limit weight points**: 5 --- ## Get ticker prices Source: https://docs.bitvavo.com/docs/websocket-api/get-ticker-prices/ Returns prices of the latest trades on Bitvavo for all markets or a single `market`. :::info A _tick_ in a market is any change in the price of a digital asset. ::: **Rate limit weight points**: 1 --- ## Get ticker book Source: https://docs.bitvavo.com/docs/websocket-api/get-ticker-book/ Stream 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 --- ## Get candlestick data Source: https://docs.bitvavo.com/docs/websocket-api/get-candlestick-data/ Returns the [OHLCV](https://www.investopedia.com/terms/o/ohlcchart.asp) market data used to create [candlestick charts](https://learn.bitvavo.com/article/what-are-candlestick-patterns/1199). Candlestick data is always returned in chronological order from the latest to the earliest. Data is returned when trades are made in the `interval` represented by that candlestick. If no trades occur you see a gap in data flow - zero trades are represented by zero candlesticks. **Rate limit weight points**: 1 --- ## Get ticker data 24h Source: https://docs.bitvavo.com/docs/websocket-api/get-ticker-data-24-h/ Streams the [OHLCV](https://www.investopedia.com/terms/o/ohlcchart.asp) data about trades and orders for all markets, or a single `market`, on Bitvavo during the latest 24 hours. **Rate limit weight points**: **25** (without `market`) or **1** (with `market`). --- ## Create order Source: https://docs.bitvavo.com/docs/websocket-api/create-order/ Creates an order to buy or sell digital assets on Bitvavo. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: :::warning You can have a maximum of [100 open orders](/docs/rest-api/get-orders) at any one time in each `market`. :::: **Rate limit weight points**: **1** --- ## Update order Source: https://docs.bitvavo.com/docs/websocket-api/update-order/ Updates an existing *limit* or *trigger* order. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: :::info You must set either `orderId` or `clientOrderId`. If you set both, we use the `clientOrderId` to identify the order. `clientOrderId` is only returned if you set it when you created the order. ::: :::tip Updating an order is faster than canceling and creating new orders. During the update, your order is briefly removed from the order book. ::: **Rate limit weight points**: 1 --- ## Get order Source: https://docs.bitvavo.com/docs/websocket-api/get-order/ Returns information about an existing order. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: :::info You must set either `orderId` or `clientOrderId`. If you set both, we use the `clientOrderId` to identify the order. `clientOrderId` is only returned if you set it when you created the order. ::: **Rate limit weight points**: **1** --- ## Cancel order Source: https://docs.bitvavo.com/docs/websocket-api/cancel-order/ Cancels an open order. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: :::info You must set either `orderId` or `clientOrderId`. If you set both, we use the `clientOrderId` to identify the order. `clientOrderId` is only returned if you set it when you created the order. ::: **Rate limit weight points**: **1** --- ## Get open orders Source: https://docs.bitvavo.com/docs/websocket-api/get-open-orders/ Returns all current open orders. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: **Rate limit weight points**: **100** (without `market`) or **5** (with `market`). --- ## Get trade history Source: https://docs.bitvavo.com/docs/websocket-api/get-trade-history/ Returns the specified number of past trades for your account and a time period of up to 24 hours. Does not return trades with a Price Guarantee. The returned trades are sorted by their `timestamp` in a descending order, from the latest to the earliest. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: :::tip To get a specific list of trades, use the `start`, `end`, `tradeIdFrom`, and `tradeIdTo` parameters. :::: :::tip To get all past transactions for your account, use the [privateGetTransactionHistory](/docs/websocket-api/get-transaction-history/) message. :::: **Rate limit weight points**: **5** --- ## Get orders Source: https://docs.bitvavo.com/docs/websocket-api/get-orders/ Returns information about multiple orders. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: **Rate limit weight points**: **5** --- ## Cancel orders Source: https://docs.bitvavo.com/docs/websocket-api/cancel-orders/ Cancels multiple orders for the specified market or the account. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: **Rate limit weight points**: **100** (without `market`) or **25** (with `market`). --- ## Atomic cancel orders Source: https://docs.bitvavo.com/docs/websocket-api/atomic-cancel-orders/ Cancels all open orders to buy or sell in the specified `market` as a single atomic request. The request is processed in strict arrival order and executed without interleaving with other operations. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: **Rate limit weight points**: **100** --- ## Cancel orders after Source: https://docs.bitvavo.com/docs/websocket-api/cancel-orders-after/ Creates an identifier used to group open orders and sets the countdown timer after which those orders are automatically canceled. To learn how to use this endpoint, see [Cancel on disconnect](/docs/cancel-on-disconnect/). :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: :::info You can create only one group. If you need to create multiple groups, reach out to your Bitvavo contact to enable this. ::: **Rate limit weight points**: **5** --- ## Get deposit data Source: https://docs.bitvavo.com/docs/websocket-api/get-deposit-data/ Returns wallet or bank account information required to deposit digital or fiat assets. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: **Rate limit weight points**: **1** --- ## Get deposit history Source: https://docs.bitvavo.com/docs/websocket-api/get-deposit-history/ Returns all past deposits for your account. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: **Rate limit weight points**: **5** --- ## Withdraw assets Source: https://docs.bitvavo.com/docs/websocket-api/withdraw-assets/ Request to withdraw assets to a wallet or bank account. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: :::warning 2FA and address confirmation by email are disabled for withdrawals using the API. ::: **Rate limit weight points**: **1** --- ## Withdraw crypto assets Source: https://docs.bitvavo.com/docs/websocket-api/withdraw-crypto-assets/ Request to withdraw crypto assets to a wallet over the specified network. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: **Rate limit weight points**: **25** --- ## Get withdrawal history Source: https://docs.bitvavo.com/docs/websocket-api/get-withdrawal-history/ Returns all past withdrawals for your account. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: **Rate limit weight points**: **5** --- ## Get account fees Source: https://docs.bitvavo.com/docs/websocket-api/get-account-fees/ Returns your current trading fees from the default [Category A](https://bitvavo.com/en/fees) based on the trading volume of your account. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: **Rate limit weight points**: **1** --- ## Get account balance Source: https://docs.bitvavo.com/docs/websocket-api/get-account-balance/ Returns the current balance for your account. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: **Rate limit weight points**: **5** --- ## Get market fees Source: https://docs.bitvavo.com/docs/websocket-api/get-market-fees/ Returns your current trading fees from the [Category](https://bitvavo.com/en/fees) of the specified market based on the trading volume of your account. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: **Rate limit weight points**: **1** --- ## Get transaction history Source: https://docs.bitvavo.com/docs/websocket-api/get-transaction-history/ Returns a list of past transactions for your account or the specified date range. If the range is not specified, returns all past transactions. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: **Rate limit weight points**: **1** --- ## Get server time Source: https://docs.bitvavo.com/docs/websocket-api/get-server-time/ Returns the current Unix timestamp of Bitvavo servers. **Rate limit weight points**: **1** --- ## Get markets Source: https://docs.bitvavo.com/docs/websocket-api/get-markets/ Returns the information about one or all markets on Bitvavo. **Rate limit weight points**: **1** --- ## Get asset data Source: https://docs.bitvavo.com/docs/websocket-api/get-asset-data/ Returns the information about the specified assets. **Rate limit weight points**: **1** --- ## Ticker subscription Source: https://docs.bitvavo.com/docs/websocket-api/ticker-subscription/ Subscribes to ticker events which return an object every time the best bid or ask changes. --- ## Ticker 24 hour subscription Source: https://docs.bitvavo.com/docs/websocket-api/ticker-24-hour-subscription/ Subscribes to ticker24h events. Every second, it returns an object with the best bids and asks in the last 24 hours. --- ## Candles subscription Source: https://docs.bitvavo.com/docs/websocket-api/candles-subscription/ Subscribes to events that return data used to form candlestick charts. --- ## Trades subscription Source: https://docs.bitvavo.com/docs/websocket-api/trades-subscription/ Subscribes to events that return data when a trade is made. --- ## Book subscription Source: https://docs.bitvavo.com/docs/websocket-api/book-subscription/ Subscribes to events that return data when there is a change in the order book. --- ## Track your orders Source: https://docs.bitvavo.com/docs/websocket-api/track-your-orders/ Subscribes to events that return data when your orders in the specified market are updated. You can receive one of the following events: - **Subscribe**: receive a confirmation that you subscribed to the channel. - **Order**: receive data about all orders you created or updated. - **Fill**: receive data about all fills or trades executed for an orders you created. :::info *Authentication required*. To send messages, you need to [authenticate connection](/docs/websocket-api/introduction/). ::: --- ## Introduction Source: https://docs.bitvavo.com/docs/ws-market-data-pro-api/introduction/ Low-latency WebSocket feed for real-time market data on Bitvavo. Provides order book snapshots, ticker prices, trades, and streaming subscriptions for book updates, ticker events, and trade events. :::info WS Market Data Pro API requires authentication for all actions and subscription channels. ::: For the complete AsyncAPI reference, see the WS Market Data Pro API specs. ### Authentication For messages that require authentication, you must first send a message to authenticate your WebSocket connection. After the connection is authenticated, you can start sending messages to the WebSocket API. To do this, you need to: 1. Create a [signature](#create-a-signature). 2. Send an [action to authenticate](#step-2-send-an-action-to-authenticate) your connection. #### Step 1: Create a signature {/* #create-a-signature */} You first need to create an HMAC-SHA256 hex-encoded `signature`: 1. Prepare the parameter values: - `timestamp`: **1548175200641** - `method`: **GET** - `path`: **/v2/websocket** - `body`: do *not* include a body. 2. Concatenate the values without a delimiter: ```text title="Concatenated string" 1548175200641GET/v2/websocket ``` 3. Prepare the API `secret` for your `Bitvavo-Access-Key`. For example: ```text title="API secret" bitvavo ``` 4. Encode the concatenated string to HMAC-SHA256 using the API `secret` for your API `key`. You get: ```text title="Signature" 653fc0505431c63a043273da4bd2f0927eae83948d796084f313e5d1131b0d6f ``` #### Step 2: Send an action to authenticate {/* #step-2-send-an-action-to-authenticate */} Now that you have created a signature, to authenticate your connection to the WebSocket API: 1. Connect to `wss://ws-mdpro.bitvavo.com/v2/` 2. Create a JSON object with: - `action`: **authenticate** - `key`: **YOUR_API_KEY** - `signature`: the [signature](#create-a-signature) you created. - `timestamp`: the Unix timestamp in milliseconds of the time you make the request. - `window` (*optional*): the time in milliseconds in which your request is allowed to execute. The default value is **10000**, and the maximum value is **60000**. 3. Send the message to the WebSocket API: ```json title="Authenticate message" { "action": "authenticate", "key": "YOUR_API_KEY", "signature": "653fc0505431c63a043273da4bd2f0927eae83948d796084f313e5d1131b0d6f", "timestamp": 1548175200641 } ``` 4. Your connection is now authenticated, and you can start sending messages to the WebSocket API. ### Permissions To use the WS Market Data Pro API from your app, make sure to add at least the following permission to your [API key](https://account.bitvavo.com/user/api) in your [Bitvavo dashboard](https://account.bitvavo.com/user/api): - **Read-only**: retrieve information about your account and transfers. To retrieve order and trade information, your API key must also have the **Trade digital assets** permission. ### See also - [Stream data with WS Market Data Pro](/docs/ws-market-data-pro-sync/) --- ## Get order book Source: https://docs.bitvavo.com/docs/ws-market-data-pro-api/get-order-book/ Returns the list of up to 1000 bids and asks per request for the specified `market`, sorted by `price`. **Rate limit weight points**: 1 --- ## Get ticker prices Source: https://docs.bitvavo.com/docs/ws-market-data-pro-api/get-ticker-prices/ Returns prices of the latest trades on Bitvavo for all markets or a single `market`. :::info A _tick_ in a market is any change in the price of a digital asset. ::: **Rate limit weight points**: 1 --- ## Get ticker book Source: https://docs.bitvavo.com/docs/ws-market-data-pro-api/get-ticker-book/ Stream 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 --- ## Get trades Source: https://docs.bitvavo.com/docs/ws-market-data-pro-api/get-trades/ Returns trades for the specified `market` and time period made by all Bitvavo users. The returned trades are sorted by their `timestamp` in a descending order, from the latest to the earliest. **Rate limit weight points**: 5 --- ## Get markets Source: https://docs.bitvavo.com/docs/ws-market-data-pro-api/get-markets/ Returns the information about one or all markets on Bitvavo. **Rate limit weight points**: **1** --- ## Get asset data Source: https://docs.bitvavo.com/docs/ws-market-data-pro-api/get-asset-data/ Returns the information about the specified assets. **Rate limit weight points**: **1** --- ## Book subscription Source: https://docs.bitvavo.com/docs/ws-market-data-pro-api/book-subscription/ Subscribes to events that return data when there is a change in the order book. --- ## Ticker subscription Source: https://docs.bitvavo.com/docs/ws-market-data-pro-api/ticker-subscription/ Subscribes to ticker events which return an object every time the best bid or ask changes. --- ## Trades subscription Source: https://docs.bitvavo.com/docs/ws-market-data-pro-api/trades-subscription/ Subscribes to events that return data when a trade is made. --- ## Introduction Source: https://docs.bitvavo.com/docs/institutional-api/introduction/ The Institutional APIs enable you to create and manage multiple subaccounts under one main account. You can use them for different trading strategies per subaccount, to manage trading for your customers, or move assets between your accounts. :::info Trading from your subaccount works the same as the main account. You can use the subaccount API key to make Exchange [WebSocket](/docs/websocket-api/) and [REST](/docs/rest-api/) API requests. ::: For the complete OpenAPI reference, see the Institutional APIs specs. ### Before you start Before you start integrating, make sure you have: - [Signed up for a Bitvavo corporate account](/docs/get-started/#sign-up-for-a-bitvavo-account) - [Enabled two-factor authentication](/docs/get-started/#enable-two-factor-authentication) - [Created an API key and secret](/docs/get-started/#create-an-api-key-and-secret) with the following permissions: - **Include all subaccounts** - **Internal Transfer** - **Administrative** :::info You can use the **Institutional** dashboard at `https://account.bitvavo.com/company/orders` to manually create subaccounts, add or transfer assets, and check balances. You can also use this dashboard to create API credentials for your subaccounts. ::: ### Authentication Learn how to authenticate your requests to Bitvavo Institutional APIs.~ ### Headers To authenticate requests, you need to add a [signature](#create-a-signature) with the following HTTP headers in every request to Bitvavo REST API: - `Bitvavo-Access-Key` (*required*): an [API Key](/docs/get-started/#create-an-api-key-and-secret) with the required permissions. - `Bitvavo-Access-Timestamp` (*required*): a Unix timestamp in milliseconds of the time you make the request. - `Bitvavo-Access-Signature` (*required*): a [HMAC-SHA256 hex-encoded string](#create-a-signature) of the following values: - `secret`: the API secret for your `Bitvavo-Access-Key`. - `timestamp`: the same Unix timestamp as for `Bitvavo-Access-Timestamp`. - `method`: the HTTP method of the request. For example, **GET** or **POST**. - `path`: the API endpoint to which you make the request. For example, `/order`. - `body`: for the **GET** `method`, an empty string. For every other `method`, a request body as a string. - `Bitvavo-Access-Window` (*optional*): the execution timeout in milliseconds after `Bitvavo-Access-Timestamp`. The default value is **10000**, and the maximum value is **60000**. ### Create a signature To create the HMAC-SHA256 hex-encoded `Bitvavo-Access-Signature` (example shown for **POST** `/v2/subaccounts`): 1. Prepare the header values. For example: - `timestamp`: **1548172481125** - `method`: **POST** - `path`: **/v2/subaccounts** - `body`: **`{"name":"MY_SUBACCOUNT"}`** (*empty* string for GET) 2. Concatenate the values without a delimiter: ```text title="Concatenated string" 1548172481125POST/v2/subaccounts{"name":"MY_SUBACCOUNT"} ``` 3. Prepare the API `secret` for your `Bitvavo-Access-Key`. For example: ```text title="Example API secret" bitvavo ``` 4. Using your API `secret`, encode the concatenated string to HMAC-SHA256: ```text title="Signature encoded with the Example API secret" 35aa503b790b893187f13c5b8cb65b8e6c12bfec690d21ed340f22ee5c530546 ``` ### Rate limits There are limits to the number of API requests that you can make within one minute. Every request is allocated a number of *Rate limit weight points* which are specified on the page of the individual request. The calculation for your weight points is the same as for the [other REST APIs](/docs/rate-limits/#how-its-calculated). However, the rate limit is shared between the main account and its subaccount. This means that the weight points from all the requests you send from your main account and subaacounts are added up to weigh against the maximum rate limit. ### See also - [Get started](/docs/get-started) - [Rate limits](/docs/rate-limits) - [Handle errors](/docs/errors) - [Create subaccount](/docs/institutional-api/create-subaccount/) --- ## Create subaccount Source: https://docs.bitvavo.com/docs/institutional-api/create-subaccount/ `POST` `/subaccounts` Creates a new subaccount under the main account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/institutional-api/introduction/). ::: :::warning To use this private endpoint, you must use the API key of your main account with the **Administrative** permission. :::: **Rate limit weight points**: **5** --- ## Get subaccounts Source: https://docs.bitvavo.com/docs/institutional-api/get-subaccounts/ `GET` `/subaccounts` Retrieves the list of all subaccounts under the main account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/institutional-api/introduction/). ::: :::info To use this private endpoint, you must use the API key of your main account with the **Administrative** permission. ::: **Rate limit weight points**: **5** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `page` | query | no | Your description of the subaccount, up to 100 characters. | | `maxItems` | query | no | The maximum number of subaccounts per page. | --- ## Create transfer Source: https://docs.bitvavo.com/docs/institutional-api/create-transfer/ `POST` `/subaccounts/transfers` Makes a deposit or withdrawal by creating a transfer of assets between your subaccounts and the main account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/institutional-api/introduction/). ::: :::warning To use this private endpoint, you must use the API key of your main account with the **Internal transfer permission** permission. :::: **Rate limit weight points**: **5** --- ## Get transfers Source: https://docs.bitvavo.com/docs/institutional-api/get-transfers/ `GET` `/subaccounts/transfers` Returns information about multiple transfers of assets between a subaccount and your main account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/institutional-api/introduction/). ::: :::warning To use this private endpoint, you must use the API key of your main account with the **Internal transfer permission**. :::: **Rate limit weight points**: **5** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `subaccountId` | query | yes | The unique identifier for the subaccount. | | `clientRequestId` | query | no | Your identifier of the transfer. | | `start` | query | no | The Unix timestamp in milliseconds starting from which to return transfers. | | `end` | query | no | The Unix timestamp in milliseconds starting up to which to return transfers. | | `limit` | query | no | The maximum number of transfers to return. | --- ## Get transfer Source: https://docs.bitvavo.com/docs/institutional-api/get-transfer/ `GET` `/subaccounts/transfers/{transferId}` Returns information about a transfer of assets between a subaccount and your main account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/institutional-api/introduction/). ::: :::warning To use this private endpoint, you must use the API key of your main account with the **Internal transfer permission**. :::: **Rate limit weight points**: **5** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `transferId` | path | yes | The unique identifier for the transfer. | --- ## Get balance Source: https://docs.bitvavo.com/docs/institutional-api/get-balance/ `GET` `/institutional/subaccounts/balance` Returns the current balance for the specified subaccount. If not specified, returns the balance for the main account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/institutional-api/introduction/). ::: :::warning To use this private endpoint, you must use the API key of your main account with the **Include all subaccounts**. :::: **Rate limit weight points**: **5** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `subaccountId` | query | no | The unique identifier for the subaccount. If not specified, returns the account balance of the main account. | | `symbol` | query | no | Asset to return the balance for. If not specified, returns all assets with balance higher than 0. | --- ## Get transaction history Source: https://docs.bitvavo.com/docs/institutional-api/get-transaction-history/ `GET` `/institutional/subaccounts/history` Returns a list of past transactions for the specified subaccount or the specified date range. If the subaccount is not specified, returns transactions for all subaccounts under the main account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/institutional-api/introduction/). ::: :::warning To use this private endpoint, you must use the API key of your main account with the **Include all subaccounts**. :::: **Rate limit weight points**: **5** ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `subaccountId` | query | no | The unique identifier for the subaccount. | | `fromDate` | query | no | The Unix timestamp in milliseconds starting from which to return transactions. | | `toDate` | query | no | The Unix timestamp in milliseconds up to which to return transactions. | | `page` | query | no | The page number for the transaction history. | | `maxItems` | query | no | The maximum number of items per page in the transaction history. | | `type` | query | no | The type of transaction to return. | --- ## Get open orders Source: https://docs.bitvavo.com/docs/institutional-api/get-open-orders/ `GET` `/institutional/subaccounts/orders/open` Returns all current open orders for the specified subaccount. If not specified, returns open orders for the main account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/institutional-api/introduction/). ::: :::warning To use this private endpoint, you must use the API key of your main account with the **Include all subaccounts**. :::: **Rate limit weight points**: **100** (without `market`) or **5** (with `market`). ### Parameters | Name | In | Required | Description | | --- | --- | --- | --- | | `subaccountId` | query | no | The unique identifier for the subaccount. If not specified, returns open orders for the main account. | | `market` | query | no | The market in which to return the open orders. If not specified, all open orders are returned. | | `base` | query | no | The base asset for which to return the open orders. If neither market nor base are specified, all open orders are returned. | --- ## Cancel order Source: https://docs.bitvavo.com/docs/institutional-api/cancel-order/ `DELETE` `/institutional/subaccounts/order` Cancels a single open order for the specified subaccount. If the subaccount is not specified, cancels the order for the main account. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/institutional-api/introduction/). ::: :::warning To use this private endpoint, you must use the API key of your main account with the **Include all subaccounts**. :::: **Rate limit weight points**: **1** --- ## Cancel orders Source: https://docs.bitvavo.com/docs/institutional-api/cancel-orders/ `DELETE` `/institutional/subaccounts/orders` Cancels multiple orders for the specified subaccount or market. If the subaccount is not specified, orders for the main account are canceled. :::info This is a *private* endpoint. To send requests, you need to [authenticate](/docs/institutional-api/introduction/). ::: :::warning To use this private endpoint, you must use the API key of your main account with the **Include all subaccounts**. :::: **Rate limit weight points**: **100** (without `market`) or **25** (with `market`). --- ## Introduction Source: https://docs.bitvavo.com/docs/fix-api/introduction/ [Financial Information eXchange](https://en.wikipedia.org/wiki/Financial_Information_eXchange) (FIX) is a standard protocol for entering orders, managing positions, and receiving trade confirmations. Institutional traders and market makers use it for high-volume, low-latency order execution. FIX defines deterministic message formats, strict sequencing, replay, and session control. Bitvavo uses FIX protocol version 4.4 with custom tags to support [additional features](#features). For the Bitvavo FIX v4.4 contract, download the [FIX API XML specification](https://docs.bitvavo.com/api-specs/2026-04-28.fix.xml). ### Before you start Before you start integrating, make sure you have: - [Signed up for a Bitvavo account](/docs/get-started/#sign-up-for-a-bitvavo-account) - [Enabled two-factor authentication](/docs/get-started/#enable-two-factor-authentication) - [Created an API key and secret](/docs/get-started/#create-an-api-key-and-secret) - Contacted Bitvavo to enable FIX API access on your account ### Basic workflow 1. [Connect](#authentication) — Open a TCP connection to the test or live environment. 2. [Logon](/docs/fix-api/logon/) — Authenticate and open a FIX session. 3. [Heartbeat](/docs/fix-api/heartbeat/) — Keep the connection alive with periodic heartbeat messages. 4. Order flow — Send order requests such as [NewOrderSingle](/docs/fix-api/new-order-single/) and receive [execution reports](/docs/fix-api/execution-report/). 5. [Logout](/docs/fix-api/logout/) — Close the FIX session and disconnect. ### Authentication Open a TCP connection to the host and port for your environment using one of the endpoints below. ##### Live environment ```text title="Order entry live environment" tcp://connection.bitvavo.com:8001 ``` ##### Test environment ```text title="Order entry test environment" tcp://connection.bitvavo-uat.com:8001 ``` #### Start the FIX session After you open the TCP connection, send a [Logon message](/docs/fix-api/logon/) (`35=A`) as your first message. Set at least these fields in your Logon. Use the same procedure for test and live. For every field, see [Logon (35=A)](/docs/fix-api/logon/). - `553` (`Username`): Set to your FIX API key. For test, use the UAT API key from Bitvavo for test. For live, use the API key you created in your dashboard for production. - `554` (`Password`): Set to the [Hex-encoded HMAC-SHA256 signature](/docs/fix-api/logon/#create-a-signature) from your API secret. :::warning Set `49` (`SenderCompID`) and `56` (`TargetCompID`) correctly in every FIX message. For details, see [Standard header](/docs/fix-api/message-structure/#standard-header). ::: ### Features The Bitvavo FIX API also supports the following custom features: #### Cancel on disconnect {/* #cancel-on-disconnect */} You can use *Cancel on disconnect* to automatically cancel your open orders if there is no [heartbeat](/docs/fix-api/heartbeat/) received within the specified interval. This prevents orders remaining open and being filled at unfavorable prices while you are disconnected. To enable this, set the `EnableCOD` (5001) tag to **Y** in your [Logon message](/docs/fix-api/logon/). ### Limitations {/* #limitations */} In every FIX session, we use the `MsSeqNo` (34) tag to track the sequence number of messages. This helps detect gaps in updates or duplicate messages. In the UAT environment, the maximum value for the `MsSeqNo` is **200000000**. Before you reach it, you need to send a new [Logon message](/docs/fix-api/logon/) with `ResetSeqNumFlag` (141) set to **Yes**. ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Order lifecycle](/docs/order-lifecycle/) - [Message structure](/docs/fix-api/message-structure/) - [Logon (35=A)](/docs/fix-api/logon/) - [NewOrderSingle (35=D)](/docs/fix-api/new-order-single/) --- ## Message structure Source: https://docs.bitvavo.com/docs/fix-api/message-structure/ Every FIX message consists of three main components that define its structure and content: - [Standard header](#standard-header) - [Message body](#message) - [Standard trailer](#standard-trailer) ### Standard header The standard header is required at the beginning of every FIX message. It provides key information about the message type and sequence number, who the sender and the receiver are, sending time, and the protocol version. :::important For messages from your system to Bitvavo, use your unique account identifier as the `SenderCompID (49)` and **VAVO** as the `TargetCompID (56)`. For messages from Bitvavo to your system, the values in these fields are reversed: `SenderCompID (49)` is **VAVO** and `TargetCompID (56)` is your unique account identifier. ::: | Tag | Name | Description | |:-----|:---------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `8` | `BeginString` | The FIX protocol version. Must be **FIX.4.4** and the first field in the message. | | `9` | `BodyLength` | The message length in bytes from this field to the `CheckSum` field.
*This must always be the second field in the message*.
| | `35` | `MsgType` | The type of message. Must be the third field in the message. For example, **35=D** is `NewOrderSingle`. | | `49` | `SenderCompID` | The sender. In messages to Bitvavo, this is your unique account identifier. In messages to you, the value is **VAVO**. | | `56` | `TargetCompID` | The recipient. In messages to Bitvavo, the value must be **VAVO**. In messages to you, this is your unique account identifier. | | `34` | `MsgSeqNo` | The sequence number of the message. Used to detect gaps or duplicate messages.
In the UAT environment, the maximum value for `MsSeqNo` is **10000000**. Before you reach it, you need to send a new [Logon message](/docs/fix-api/logon/) with `ResetSeqNumFlag` (141) set to **Yes** .
| | `52` | `SendingTime` | The UTC timestamp in nanoseconds when the message was sent. Must be in the format `YYYYMMDD-HH:MM:SS.sssssssss`, for example `20260115-10:05:54.794327000`. | ### Message body {/* #message */} The message body contains a set of tags relevant to each message type. After constructing the standard header, include the tags specified for the message you want to send or receive. You can find the messages we support below: #### Admin - [Logon (35=A)](/docs/fix-api/logon/) - [Logout (35=5)](/docs/fix-api/logout/) - [Heartbeat (35=0)](/docs/fix-api/heartbeat/) - [Reject (35=3)](/docs/fix-api/reject/) - [Resend Request (35=2)](/docs/fix-api/resend-request/) - [Test Request (35=1)](/docs/fix-api/test-request/) - [Sequence Reset (35=4)](/docs/fix-api/sequence-reset/) #### Trading - [NewOrderSingle (35=D)](/docs/fix-api/new-order-single/) - [OrderCancelReplaceRequest (35=G)](/docs/fix-api/order-cancel-replace-request/) - [OrderCancelRequest (35=F)](/docs/fix-api/order-cancel-request/) - [OrderMassCancelRequest (35=q)](/docs/fix-api/order-mass-cancel-request/) - [OrderStatusRequest (35=H)](/docs/fix-api/order-status-request/) - [OrderMassStatusRequest (35=AF)](/docs/fix-api/order-mass-status-request/) - [BusinessMessageReject (35=j)](/docs/fix-api/business-message-reject/) - [OrderMassCancelReport (35=r)](/docs/fix-api/order-mass-cancel-report/) - [ExecutionReport (35=8)](/docs/fix-api/execution-report/) - [OrderCancelReject (35=9)](/docs/fix-api/order-cancel-reject/) #### Drop copy - [ExecutionReport (35=8)](/docs/fix-api/execution-report/) - [OrderCancelReject (35=9)](/docs/fix-api/order-cancel-reject/) ### Standard trailer The standard trailer is required at the end of every FIX message. It marks the end of the message and includes a checksum field to verify that the message was transmitted correctly. | Tag | Name | Type | Required | Description | |:-----|:-----------|:-------|:---------|:---------------------------------------------------------| | `10` | `CheckSum` | String | Y | Three-byte checksum used to mark the end of the message. | ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Logon (35=A)](/docs/fix-api/logon/) - [Logout (35=5)](/docs/fix-api/logout/) - [Heartbeat (35=0)](/docs/fix-api/heartbeat/) - [Reject (35=3)](/docs/fix-api/reject/) - [Test Request (35=1)](/docs/fix-api/test-request/) - [Resend Request (35=2)](/docs/fix-api/resend-request/) --- ## Logon (35=A) Source: https://docs.bitvavo.com/docs/fix-api/logon/ Authenticates and opens a FIX session. Must be the first message sent by the application requesting to initiate a FIX session. ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} | Tag | Name | Type | Required | Description | |:-------|:-------------------|:--------|:---------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `98` | `EncryptMethod` | Int | Y | Must be: **0** None / Other. | | `108` | `HeartBtInt` | Int | Y | Heartbeat interval in seconds. Recommended value: **30**. | | `141` | `ResetSeqNumFlag` | Boolean | N | Indicates that both sides of the FIX session should reset sequence numbers.
Can be:
  • `N`: No
  • `Y`: Yes
| | `553` | `Username` | String | Y | Your [API key](/docs/get-started/#create-an-api-key-and-secret). | | `554` | `Password` | String | Y | [HMAC-SHA256 hex-encoded signature](#create-a-signature) created from your API secret. | | `5001` | `EnableCOD` | Boolean | Y | ***Custom Bitvavo tag***
Indicates whether to enable [Cancel on Disconnect](#cancel-on-disconnect) feature for this session.
Can be:
  • `N`: Disabled
  • `Y`: Enabled
| #### Cancel on disconnect {/* #cancel-on-disconnect */} You can use *Cancel on disconnect* to automatically cancel your open orders if there is no [heartbeat](/docs/fix-api/heartbeat/) received within the specified interval. This prevents orders remaining open and being filled at unfavorable prices while you are disconnected. To enable this, set the `EnableCOD` (`5001`) tag to **Y**. ### Create a signature {/* #create-a-signature */} Before testing, request your UAT credentials from your Bitvavo contact. For the live environment, use your your production [API credentials](/docs/get-started/#create-an-api-key-and-secret). 1. Prepare the input values: - `api_key`: **YOUR_API_KEY** - `SenderCompID`: **YOUR_UNIQUE_ACCOUNT_IDENTIFIER** - `seqNum`: **1** - `sendingTime`: the Unix timestamp in milliseconds, converted from the value of the FIX header tag `52` generated by your FIX engine, for example: **1700000000123** :::important FIX engines automatically populate this field when you create the Logon message. Your app must read the value from the message header for every Logon message and convert it to milliseconds since Unix epoch to generate the signature. ::: ``` text title="SendingTime to Unix timestamp in milliseconds" SendingTime (tag 52) = 2023-11-14T12:13:20.123Z sendingTime (ms) = 1700000000123 ``` 1. Concatenate the values without a delimiter: ```text title="Concatenated string" YOUR_API_KEYYOUR_UNIQUE_ACCOUNT_IDENTIFIER11700000000123 ``` 2. Prepare the API `secret` for associated with your API key. For example: ```text title="API secret" bitvavo ``` 3. To get the `Password`, encode the concatenated string to HMAC-SHA256 using the API `secret` for your API `key`. ```text title="Generation logic" password = hmac.new(secret, message_input_str, hashlib.sha256).hexdigest() ``` 4. You get the following signature to use as the `Password`: ```text title="Signature" 50b24049b5764748e7d1096449959fb01254fb326d86aaf04dff6c2993fe41a6 ``` ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [NewOrderSingle](/docs/fix-api/new-order-single/) - [OrderCancelReplaceRequest](/docs/fix-api/order-cancel-replace-request/) - [ExecutionReport](/docs/fix-api/execution-report/) - [OrderCancelReject](/docs/fix-api/order-cancel-reject/) --- ## Logout (35=5) Source: https://docs.bitvavo.com/docs/fix-api/logout/ Closes a FIX session. Must be the last message sent by the application that initiated the FIX session. ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} | Tag | Name | Type | Required | Description | |:------|:-------|:-------|:---------|:------------------------| | `58` | `Text` | String | N | Reason for logging out. | ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [NewOrderSingle](/docs/fix-api/new-order-single/) - [OrderCancelReplaceRequest](/docs/fix-api/order-cancel-replace-request/) - [ExecutionReport](/docs/fix-api/execution-report/) - [OrderCancelReject](/docs/fix-api/order-cancel-reject/) --- ## Heartbeat (35=0) Source: https://docs.bitvavo.com/docs/fix-api/heartbeat/ Periodic message that confirms that the FIX session is active. Can also be sent as the response to the Test Request message (35=1). ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) - ### Message body {/* #message */} **Required** column values: - **Y** = Required - **N** = Not required - **C** = Conditionally required (depends on another parameter) | Tag | Name | Type | Required | Description | |:-------|:------------|:-------|:---------|:---------------------------------------------------------------------| | `112` | `TestReqID` | String | C | Required when the heartbeat is the result of a Test Request message. | ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Logon](/docs/fix-api/logon/) - [Logout](/docs/fix-api/logout/) - [Message structure](/docs/fix-api/message-structure/) --- ## Reject (35=3) Source: https://docs.bitvavo.com/docs/fix-api/reject/ Sent when a message violates session-level rules and cannot be processed. For example, when required header fields or basic message structure are invalid. ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} | Tag | Name | Type | Required | Description | |:------|:----------------------|:-------|:---------|:---------------------------------------------------------------------------------------| | `45` | `RefSeqNum` | Int | Y | Sequence number of the rejected message. | | `371` | `RefTagID` | Int | N | Tag number of the field that caused rejection. | | `372` | `RefMsgType` | String | N | Message type of the rejected message. | | `373` | `SessionRejectReason` | Int | N | Reason code for rejection. Possible values are [below](#session-reject-reason-values). | | `58` | `Text` | String | N | Textual description of the rejection. | #### SessionRejectReason values {/* #session-reject-reason-values */} | Value | Description | |:------|:----------------------------------------------------------------------------------------------------| | `0` | Invalid tag number | | `1` | Required tag missing | | `2` | Tag not defined for this message type | | `3` | Undefined tag | | `4` | Tag specified without a value | | `5` | Value is incorrect (out of range) for this tag | | `6` | Incorrect data format for value | | `7` | Decryption problem | | `8` | Signature problem | | `9` | CompID problem | | `10` | SendingTime accuracy problem | | `11` | Invalid `MsgType` | | `12` | XML validation error | | `13` | Tag appears more than once | | `14` | Tag specified out of required order | | `15` | Repeating group fields out of order | | `16` | Incorrect `NumInGroup` count for repeating group | | `17` | Non-data value includes field delimiter (`` character) | | `18` | Invalid or unsupported application version | | `99` | Other | ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [NewOrderSingle](/docs/fix-api/new-order-single/) - [OrderCancelReplaceRequest](/docs/fix-api/order-cancel-replace-request/) - [ExecutionReport](/docs/fix-api/execution-report/) --- ## ResendRequest (35=2) Source: https://docs.bitvavo.com/docs/fix-api/resend-request/ Sent to request the other side to resend missed messages when a sequence gap is detected or when initiating a session. ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} | Tag | Name | Type | Required | Description | |:------|:-------------|:-------|:---------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------| | `7` | `BeginSeqNo` | SeqNum | Y | Starting sequence number of the range to resend. | | `16` | `EndSeqNo` | SeqNum | Y | Ending sequence number of the range to resend. Use `0` to request all messages after the `BeginSeqNo`.
For a single message, `BeginSeqNo` = `EndSeqNo`. | ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [NewOrderSingle](/docs/fix-api/new-order-single/) - [OrderCancelReplaceRequest](/docs/fix-api/order-cancel-replace-request/) - [ExecutionReport](/docs/fix-api/execution-report/) --- ## TestRequest (35=1) Source: https://docs.bitvavo.com/docs/fix-api/test-request/ Sent to request the other side to send a [Heartbeat](/docs/fix-api/heartbeat/) so you can confirm the connection is working. ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} | Tag | Name | Type | Required | Description | |:-------|:------------|:-------|:---------|:--------------------------------------------------------------| | `112` | `TestReqID` | String | Y | Identifier to be returned in the resulting Heartbeat message. | ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [NewOrderSingle](/docs/fix-api/new-order-single/) - [OrderCancelReplaceRequest](/docs/fix-api/order-cancel-replace-request/) - [ExecutionReport](/docs/fix-api/execution-report/) --- ## SequenceReset (35=4) Source: https://docs.bitvavo.com/docs/fix-api/sequence-reset/ Resets the inbound or outbound sequence numbers in a session. :::warning Incorrect usage can lead to a mismatch in sequence numbers and desynchronize the session. ::: ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} | Tag | Name | Type | Required | Description | |:-------|:--------------|:--------|:---------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `123` | `GapFillFlag` | Boolean | Y | Indicates whether to resend admin or application messages. Possible values:
  • `Y`: Gap fill. Messages up to `NewSeqNo` are skipped.
  • `N`: Sequence reset. Sequence number is reset to the `NewSeqNo` (higher than the existing sequence number).
| | `36` | `NewSeqNo` | SeqNum | Y | The sequence number that the following messages must use. Must be higher than the currently expected sequence number. | ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [ResendRequest (35=2)](/docs/fix-api/resend-request/) - [TestRequest (35=1)](/docs/fix-api/test-request/) --- ## NewOrderSingle (35=D) Source: https://docs.bitvavo.com/docs/fix-api/new-order-single/ Creates a new order to buy or sell a digital asset on Bitvavo. **Rate limit weight points: 1** ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} **Required** column values: - **Y** = Required - **N** = Not required - **C** = Conditionally required (depends on another parameter) | Tag | Name | Type | Required | Description | |:-------|:---------------------------------|:------------------|:---------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `2422` | `OrderRequestID` | Int | N | Your unique identifier of the request. | | `60` | `TransactTime` | UTCTimestamp | Y | The UTC timestamp in nanoseconds when the order was created. Must be in the format `YYYYMMDD-HH:MM:SS.sssssssss`, for example `20260115-10:05:54.794327000`. | | `1` | `Account` | String | N | The unique identifier of the account.
If not specified, the `SenderCompID` is used.
| | `55` | `Symbol` | String | Y | The market in which the order was created, for example **BTC-EUR**. | | `11` | `ClOrdID` | String | Y | Your identifier of the order. Must be a valid `UUID`, for example **1be6d0df-d5dc-4b53-a250-3376f3b393e6**. | | `54` | `Side` | Char | Y | Indicates whether the order is to buy or sell the asset.
Can be:
  • `1`: Buy
  • `2`: Sell
| | `40` | `OrdType` | Char | Y | The type of order you create.
Can be:
  • `1`: Market
  • `2`: Limit
  • `3`: Stop
  • `4`: Stop Limit
| | `38` | `OrderQty` | Qty | C | The quantity of the base currency (for example **BTC**) to buy or sell.
Required if `CashOrderQty` is not provided. | | `152` | `CashOrderQty` | Qty | C | The quantity of the quote currency (for example **EUR**) to buy or sell for the market, stop, or stop limit order types.
Required if `OrderQty` is not provided. | | `44` | `Price` | Price | C | The price in quote currency.
Must be a multiple of the `tickSize` value for the market.
| | `99` | `StopPx` | Price | C | The trigger price in quote currency. Required for stop and stop limit orders. | | `1107` | `TriggerPriceType` | Char | C | The price which triggers the order to be filled.
Can be:
  • `1`: Best Offer
  • `2`: Last Trade
  • `3`: Best Bid
  • `6`: Best Mid
| | `59` | `TimeInForce` | Char | N | How long an order stays active for.
Can be:
  • `1`: Good Till Cancel (GTC)
  • `3`: Immediate Or Cancel (IOC)
  • `4`: Fill Or Kill (FOK)
| | `18` | `ExecInst` | MultipleCharValue | N | Set to `6` to mark the order as `postOnly` (adds liquidity to the order book). | | `2964` | `SelfMatchPreventionInstruction` | Char | N | Prevents self-trading for conflicting orders.
Can be:
  • `1`: Cancel aggressive (newest)
  • `2`: Cancel passive (oldest)
  • `3`:Cancel both
  • `4`: Decrement and cancel (***Custom Bitvavo value***)
| | `5002` | `OperatorID` | Int | Y | ***Custom Bitvavo tag***
Your identifier for the trader or the bot within your account that made the request. | ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [ExecutionReport](/docs/fix-api/execution-report/) - [OrderCancelRequest](/docs/fix-api/order-cancel-request/) - [OrderCancelReplaceRequest](/docs/fix-api/order-cancel-replace-request/) --- ## OrderCancelReplaceRequest (35=G) Source: https://docs.bitvavo.com/docs/fix-api/order-cancel-replace-request/ Updates an existing limit or trigger order to buy or sell digital assets on Bitvavo. **Rate limit weight points: 1** ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} **Required** column values: - **Y** = Required - **N** = Not required - **C** = Conditionally required (depends on another parameter) | Tag | Name | Type | Required | Description | |:-------|:---------------------------------|:------------------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `2422` | `OrderRequestID` | Int | N | Your unique identifier of the request. | | `60` | `TransactTime` | UTCTimestamp | Y | The UTC timestamp in nanoseconds when the order was created. Must be in the format `YYYYMMDD-HH:MM:SS.sssssssss`, for example `20260115-10:05:54.794327000`. | | `1` | `Account` | String | N | The unique identifier of the account.
If not specified, the `SenderCompID` is used.
| | `55` | `Symbol` | String | Y | The market in which the order was created, for example **BTC-EUR**. | | `37` | `OrderID` | String | C | Bitvavo identifier of the order to update. Required if `OrigClOrdID` is not specified. | | `11` | `ClOrdID` | String | Y | Your new identifier of the order, that will replace the original `ClOrdID` (returned in `OrigClOrdID`). Must be a valid `UUID`, for example **1be6d0df-d5dc-4b53-a250-3376f3b393e6**. | | `41` | `OrigClOrdID` | String | C | The original identifier `ClOrdID (11)` of the order that you want to update.
Required if `OrderID` is not specified.
If both `OrderID` and `OrigClOrdID` are specified, `OrigClOrdID` has precedence. | | `54` | `Side` | Char | Y | Indicates whether the order is to buy or sell the asset.
This is a required tag, but Bitvavo ignores the value.
| | `38` | `OrderQty` | Qty | N | The new quantity of the base currency (for example **BTC**) to buy or sell. | | `152` | `CashOrderQty` | Qty | N | The quantity of the quote currency (for example **EUR**) to buy or sell for untriggered stop and stop limit order types. | | `44` | `Price` | Price | N | The new price in quote currency.
Must be a multiple of the `tickSize` value for the market.
| | `18` | `ExecInst` | MultipleCharValue | N | The new execution instruction. Set to `6` to mark the order as `postOnly` (adds liquidity to the order book). | | `2964` | `SelfMatchPreventionInstruction` | Char | N | The new self-trading prevention instruction.
Can be:
  • `1`: Cancel aggressive (newest)
  • `2`: Cancel passive (oldest)
  • `3`:Cancel both
  • `4`: Decrement and cancel (***Custom Bitvavo value***)
| | `99` | `StopPx` | Price | N | The new trigger price in quote currency. Only applicable to untriggered stop and stop limit orders. | | `59` | `TimeInForce` | Char | N | How long an order stays active for.
Can be:
  • `1`: Good Till Cancel (GTC)
  • `3`: Immediate Or Cancel (IOC)
  • `4`: Fill Or Kill (FOK)
| | `5002` | `OperatorID` | Int | Y | ***Custom Bitvavo tag***
Your identifier for the trader or the bot within your account that made the request. | | `40` | `OrdType` | Char | Y | The type of order you create.
This is a required tag, but Bitvavo ignores the value.
| ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [NewOrderSingle](/docs/fix-api/new-order-single/) - [OrderCancelRequest](/docs/fix-api/order-cancel-request/) - [ExecutionReport](/docs/fix-api/execution-report/) - [OrderCancelReject](/docs/fix-api/order-cancel-reject/) --- ## OrderCancelRequest (35=F) Source: https://docs.bitvavo.com/docs/fix-api/order-cancel-request/ Cancels an open order to buy or sell a digital asset on Bitvavo. **Rate limit weight points: 1** ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} **Required** column values: - **Y** = Required - **N** = Not required - **C** = Conditionally required (depends on another parameter) | Tag | Name | Type | Required | Description | |:-------|:-----------------|:-------------|:---------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `2422` | `OrderRequestID` | Int | Y | Your unique identifier of the request. | | `60` | `TransactTime` | UTCTimestamp | Y | The UTC timestamp in nanoseconds when the order was created. Must be in the format `YYYYMMDD-HH:MM:SS.sssssssss`, for example `20260115-10:05:54.794327000`. | | `1` | `Account` | String | N | The unique identifier of the account.
If not specified, the `SenderCompID` is used.
| | `55` | `Symbol` | String | Y | The market in which the order was created, for example **BTC-EUR**. | | `37` | `OrderID` | String | C | Bitvavo identifier of the order to cancel. Required if `OrigClOrdID` is not specified. | | `11` | `ClOrdID` | String | Y | Your new identifier of the order, that will replace the original `ClOrdID` (returned in `OrigClOrdID`). Must be a valid `UUID`, for example **1be6d0df-d5dc-4b53-a250-3376f3b393e6**. | | `41` | `OrigClOrdID` | String | C | The original identifier `ClOrdID (11)` of the order that you want to update.
Required if `OrderID` is not specified.
If both `OrderID` and `OrigClOrdID` are specified, `OrigClOrdID` has precedence. | | `54` | `Side` | Char | Y | Indicates whether the order is to buy or sell the asset.
Can be:
  • `1`: Buy
  • `2`: Sell
| | `5002` | `OperatorID` | Int | Y | ***Custom Bitvavo tag***
Your identifier for the trader or the bot within your account that made the request. | ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [NewOrderSingle](/docs/fix-api/new-order-single/) - [OrderCancelReplaceRequest](/docs/fix-api/order-cancel-replace-request/) - [ExecutionReport](/docs/fix-api/execution-report/) - [OrderCancelReject](/docs/fix-api/order-cancel-reject/) --- ## OrderMassCancelRequest (35=q) Source: https://docs.bitvavo.com/docs/fix-api/order-mass-cancel-request/ Cancels multiple open orders to buy or sell a digital asset on Bitvavo. You can cancel all open orders either for a specific market or all orders for the account. **Rate limit weight points**: **25** for one market (`MassCancelRequestType` = `1`) or **100** when canceling all orders for the account (`MassCancelRequestType` = `7`). ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} **Required** column values: - **Y** = Required - **N** = Not required - **C** = Conditionally required (depends on another parameter) | Tag | Name | Type | Required | Description | |:-------|:------------------------|:-------------|:---------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `11` | `ClOrdID` | String | Y | Your new identifier of the order, that will replace the original `ClOrdID`. | | `1` | `Account` | String | N | The unique identifier of the account.
If not specified , the `SenderCompID` is used.
| | `60` | `TransactTime` | UTCTimestamp | Y | The UTC timestamp in nanoseconds when the order was created. | | `530` | `MassCancelRequestType` | Char | Y | Indicates whether to cancel orders for the market or the account.
Can be:
  • `1`: Cancels all orders for the specified market
  • `7`: Cancels all orders for the specified account
| | `55` | `Symbol` | String | C | The market in which the orders were created, for example **BTC-EUR**.
Required if `MassCancelRequestType` = `1`. | | `5002` | `OperatorID` | Int | Y | ***Custom Bitvavo tag***
Your identifier for the trader or the bot within your account that made the request. | ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [NewOrderSingle](/docs/fix-api/new-order-single/) - [OrderCancelRequest](/docs/fix-api/order-cancel-request/) - [OrderCancelReplaceRequest](/docs/fix-api/order-cancel-replace-request/) - [OrderMassCancelReport](/docs/fix-api/order-mass-cancel-report/) --- ## OrderStatusRequest (35=H) Source: https://docs.bitvavo.com/docs/fix-api/order-status-request/ Retrieves details of an open order to buy or sell a digital asset on Bitvavo. **Rate limit weight points: 5** :::info Cannot be used to retrieve the details of [completed orders](/docs/order-lifecycle/#completed-orders). ::: ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} **Required** column values: - **Y** = Required - **N** = Not required - **C** = Conditionally required (depends on another parameter) | Tag | Name | Type | Required | Description | |:-------|:-----------------|:-------------|:---------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `790` | `OrdStatusReqID` | String | N | Your unique identifier of the request. | | `1` | `Account` | String | N | The unique identifier of the account.
If not specified, the `SenderCompID` is used.
| | `55` | `Symbol` | String | Y | The market in which the order was created, for example **BTC-EUR**.
This is a required tag, but Bitvavo ignores the value.
| | `37` | `OrderID` | String | C | Bitvavo identifier of the order for which to return the details. Required if `ClOrdID` is not specified. | | `11` | `ClOrdID` | String | C | Your identifier of the open order for which to return the details. Must be a valid `UUID`, for example **1be6d0df-d5dc-4b53-a250-3376f3b393e6**.
Required if `OrderID` is not specified.
If both `OrderID` and `ClOrdID` are specified, `ClOrdID` has precedence. | | `54` | `Side` | Char | Y | Indicates whether the order is to buy or sell the asset.
Can be:
  • `1`: Buy
  • `2`: Sell

This is a required tag, but Bitvavo ignores the value.
| ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [NewOrderSingle](/docs/fix-api/new-order-single/) - [OrderCancelRequest](/docs/fix-api/order-cancel-request/) - [OrderCancelReplaceRequest](/docs/fix-api/order-cancel-replace-request/) - [ExecutionReport](/docs/fix-api/execution-report/) --- ## OrderMassStatusRequest (35=AF) Source: https://docs.bitvavo.com/docs/fix-api/order-mass-status-request/ Returns the details of all open orders for a specific market or the account. **Rate limit weight points**: **25** for one market (`MassStatusReqType` = `1`) or **100** for all orders in the account (`MassStatusReqType` = `7`). ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} **Required** column values: - **Y** = Required - **N** = Not required - **C** = Conditionally required (depends on another parameter) | Tag | Name | Type | Required | Description | |:-------|:--------------------|:-------------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `584` | `MassStatusReqID` | Int | Y | Your unique identifier of the mass status request. | | `1` | `Account` | String | N | The unique identifier of the account.
If not specified, the `SenderCompID` is used.
| | `585` | `MassStatusReqType` | Char | Y | Indicates whether to get details for all orders in the market or the account.
Can be:
  • `1`: Status for all orders in the specified market
  • `7`: Status for all orders in the specified account
| | `55` | `Symbol` | String | C | The market in which the orders were created, for example **BTC-EUR**.
Required if `MassStatusReqType` = `1`, otherwise ignored if specified. | :::info Sending an `OrderMassStatusRequest` when there are no open orders will return an `ExecutionReport` with `OrdStatus` = `U` (Unknown) . ::: ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [OrderStatusRequest](/docs/fix-api/order-status-request/) - [OrderMassCancelRequest](/docs/fix-api/order-mass-cancel-request/) - [ExecutionReport](/docs/fix-api/execution-report/) --- ## BusinessMessageReject (35=j) Source: https://docs.bitvavo.com/docs/fix-api/business-message-reject/ Sent by Bitvavo when your message is rejected because of a failure in business logic or invalid message structure. ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} | Tag | Name | Type | Required | Description | |:------|:-----------------------|:--------|:---------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `372` | `RefMsgType` | String | Y | The type of the rejected message. | | `380` | `BusinessRejectReason` | Int | Y | The reason for rejection.
Can be:
  • `0`: Other
  • `1`: Unknown ID
  • `2`: Unknown security
  • `3`: Unsupported message type
  • `4`: Application not available
  • `5`: Conditionally required field missing
  • `6`: Not authorized
| | `58` | `Text` | String | N | The description of the reason for the rejection. See [Handle errors](/docs/errors/) for possible values. | | `379` | `BusinessRejectRefID` | String | N | The identifier of the rejected message. The value matches the following tags from the original message:
  • `ClOrdID (11)` for NewOrderSingle, OrderCancelReplaceRequest, OrderCancelRequest, and OrderMassCancelRequest
  • `OrdStatusReqID (790)` - OrderStatusRequest
  • `MassStatusReqID (584)` - OrderMassStatusRequest
| ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [Errors](/docs/errors/) - [NewOrderSingle](/docs/fix-api/new-order-single/) - [OrderCancelReplaceRequest](/docs/fix-api/order-cancel-replace-request/) - [OrderCancelRequest](/docs/fix-api/order-cancel-request/) --- ## OrderMassCancelReport (35=r) Source: https://docs.bitvavo.com/docs/fix-api/order-mass-cancel-report/ Sent by Bitvavo in response to your mass cancellation request. Indicates whether the request was accepted or rejected, and how many orders were affected. :::info In addition to the `OrderMassCancelReport`, you will get individual `ExecutionReport` messages for every canceled order. ::: ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} **Required** column values: - **Y** = Required - **N** = Not required - **C** = Conditionally required (depends on another parameter) | Tag | Name | Type | Required | Description | |:-------|:------------------------|:-------------|:---------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `60` | `TransactTime` | UTCTimestamp | N | The UTC timestamp in nanoseconds when the message was created. Must be in the format `YYYYMMDD-HH:MM:SS.sssssssss`, for example `20260115-10:05:54.794327000`. | | `1` | `Account` | String | Y | The unique identifier of the account. | | `11` | `ClOrdID` | String | N | Your identifier from the `OrderMassCancelRequest`. Empty if the mass cancellation was initiated by Bitvavo. | | `1369` | `MassActionReportID` | String | Y | Bitvavo identifier of the mass cancel report. | | `530` | `MassCancelRequestType` | Char | Y | The type of mass cancel request specified in the [`OrderMassCancelRequest`](/docs/fix-api/order-mass-cancel-request/).
Can be:
  • `1`: Cancels all orders for the specified market
  • `7`: Cancels all orders for the specified account
| | `531` | `MassCancelResponse` | Char | Y | The action taken by Bitvavo.
Can be:
  • `0`: Cancel request rejected (see field `58` = `Text` )
  • `1`: Canceled orders for a specific market
  • `7`: Canceled all orders for the account
| | `58` | `Text` | String | N | The description of the reason for rejection if the mass cancel request is rejected. | | `533` | `TotalAffectedOrders` | Int | C | The total number of canceled orders. Required when the cancellation is successful. | | `55` | `Symbol` | String | C | The market in which the orders were created, for example **BTC-EUR**.
Required if `MassCancelResponse` = `1`. | ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [OrderMassCancelRequest](/docs/fix-api/order-mass-cancel-request/) - [OrderCancelRequest](/docs/fix-api/order-cancel-request/) - [ExecutionReport](/docs/fix-api/execution-report/) --- ## ExecutionReport (35=8) Source: https://docs.bitvavo.com/docs/fix-api/execution-report/ Returns information about the status of orders, order changes, fills, and rejections. Sent by Bitvavo during the [order lifecycle](/docs/order-lifecycle/) to communicate updates and execution details. ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} **Required** column values: - **Y** = Required - **N** = Not required - **C** = Conditionally required (depends on another parameter) | Tag | Name | Type | Required | Description | |:-------|:---------------------------------|:-------------|:---------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `60` | `TransactTime` | UTCTimestamp | N | The UTC timestamp in nanoseconds when the message was created. Must be in the format `YYYYMMDD-HH:MM:SS.sssssssss`, for example `20260115-10:05:54.794327000`. | | `1` | `Account` | String | Y | The unique identifier of the account. | | `37` | `OrderID` | String | Y | Bitvavo identifier of the order. Must be a valid `UUID`, for example **1be6d0df-d5dc-4b53-a250-3376f3b393e6**. Empty if a new order is rejected. | | `11` | `ClOrdID` | String | Y | Your identifier of the order. Must be a valid `UUID`, for example **1be6d0df-d5dc-4b53-a250-3376f3b393e6**. | | `41` | `OrigClOrdID` | String | C | Your identifier of the order. If the order was previously updated, this is the `ClOrdID (11)` of the most recent order. | | `2422` | `OrderRequestID` | Int | C | Your unique identifier of the order request message. | | `790` | `OrdStatusReqID` | String | C | Your unique identifier of a `OrderStatusRequest` message. | | `584` | `MassStatusReqID` | Int | C | Your unique identifier of the `OrderMassStatusRequest` message. | | `1003` | `TradeID` | String | C | Bitvavo identifier of the trade. Must be a valid `UUID`, for example **1be6d0df-d5dc-4b53-a250-3376f3b393e6**. Required if `ExecType` = `F` Trade (partial fill or fill). | | `55` | `Symbol` | String | Y | The market in which the order was created, for example **BTC-EUR**.
When there are no open orders, this is set to `0` in the response to `OrderMassStatusRequest`.
| | `54` | `Side` | Char | Y | Indicates whether the order is to buy or sell the asset.
Can be:
  • `1`: Buy
  • `2`: Sell
  • `7`: Undisclosed
| | `17` | `ExecID` | String | Y | Bitvavo identifier of the execution message. Will be `0` for `ExecType` = `I` (Order Status). | | `150` | `ExecType` | Char | Y | The purpose of the execution report.
Can be:
  • `0`: New
  • `F`: Trade
  • `4`: Canceled
  • `C`: Expired
  • `5`: Replaced
  • `L`: Triggered
  • `D`: Restated
  • `8`: Rejected
  • `I`: Order status
| | `39` | `OrdStatus` | Char | Y | The current state of the order.
Can be:
  • `0`: New
  • `1`: Partially filled
  • `2`: Filled
  • `4`: Canceled
  • `8`: Rejected
  • `C`: Expired
  • `T`: Awaiting trigger
  • `U`: Unknown
| | `378` | `ExecRestatementReason` | Int | C | The reason why the status of the order was changed.
You can find the possible values [below](#exec-restatement-reason-values). | | `58` | `Text` | String | C | The description explaining the order status, execution type, or restatement reason. | | `38` | `OrderQty` | Qty | C | The quantity of the base currency (for example **BTC**). | | `152` | `CashOrderQty` | Qty | C | The quantity of the quote currency (for example **EUR**). Only applicable to market, stop, and stop limit orders. | | `151` | `LeavesQty` | Qty | Y | The quantity of the part of the order that is still open. If `CashOrderQty` was specified in the original message, the quantity is in quote currency. | | `14` | `CumQty` | Qty | Y | The total quantity that was filled. If `CashOrderQty` was specified in the original message, the quantity is in quote currency. | | `32` | `LastQty` | Qty | C | The quantity bought or sold on the last fill. Required for partial fills and fills. If `CashOrderQty` was specified in the original message, the quantity is in quote currency. | | `84` | `CxlQty` | Qty | C | The quantity that was canceled. Required if `OrdStatus` is `4` **Canceled**. | | `40` | `OrdType` | Char | N | The type of order.
Can be:
  • `1`: Market
  • `2`: Limit
  • `3`: Stop
  • `4`: Stop limit
| | `44` | `Price` | Price | N | The price in quote currency. | | `31` | `LastPx` | Price | C | The price of the last fill. Required for partial fills and fills. | | `99` | `StopPx` | Price | C | The trigger price in quote currency for stop and stop-limit orders. | | `1107` | `TriggerPriceType` | Char | C | The price which triggers the order to be filled.
Can be:
  • `1`: Best Offer
  • `2`: Last Trade
  • `3`: Best Bid
  • `6`: Best Mid
| | `59` | `TimeInForce` | Char | N | How long an order stays active for.
Can be:
  • `1`: Good Till Cancel (GTC)
  • `3`: Immediate Or Cancel (IOC)
  • `4`: Fill Or Kill (FOK)
| | `18` | `ExecInst` | MultipleChar | C | The execution instruction. If specified in the original request, usually set to `6` to mark the order as `postOnly`. | | `2964` | `SelfMatchPreventionInstruction` | Char | C | Self-trading prevention strategy for conflicting orders.
Can be:
  • `1`: Cancel aggressive (newest)
  • `2`: Cancel passive (oldest)
  • `3`:Cancel both
  • `4`: Decrement and cancel (***Custom Bitvavo value***)
| | `851` | `LastLiquidityInd` | Char | C | Indicates whether the fill added or removed liquidity.
Can be:
  • `1`: Added liquidity (maker)
  • `2`: Removed liquidity (taker)
Required for partial fills and fills. | | `5003` | `OnHold` | Amt | C | ***Custom Bitvavo tag***
The amount of `OnHoldCurrency` reserved for an order that is being processed. Required for [active orders](/docs/order-lifecycle/#active-orders). | | `5004` | `OnHoldCurrency` | Currency | C | ***Custom Bitvavo tag***
The currency reserved for an order that is being processed. This is the quote currency for sell orders and the base currency for buy orders. | | `12` | `Commission` | Currency | C | Bitvavo fees for the order. | | `2643` | `CommissionCurrency` | Currency | C | The currency in which the Bitvavo fee is paid. | | `103` | `OrdRejReason` | Int | C | The reason why a new order, order cancel request, or order cancel replace request was rejected.
You can find the possible values [below](#ord-rej-reason-values). | | `5002` | `OperatorID` | Int | N | ***Custom Bitvavo tag***
Your identifier for the trader or the bot within your account that made the request. | #### OrderRejReason values {/* #ord-rej-reason-values */} We use the standard FIX codes when available. Custom Bitvavo codes start at `101`. | Tag | Description | |:------|:--------------------------------------------------------------------------------------------------------| | `1` | Unknown symbol
The requested market does not exist or cannot be found internally. | | `2` | Exchange closed
Market is halted. | | `3` | Order exceeds limit
Account balance cannot cover the order. | | `5` | Unknown order
Order cannot be located. | | `6` | Duplicate order
Duplicate `ClOrdID` detected. | | `13` | Incorrect quantity
Base or quote quantity is malformed. | | `15` | Unknown account
The account cannot be found. | | `16` | Price exceeds current price band
Price falls outside the exchange protection bands. | | `18` | Invalid price increment
Price does not align with the market tick size. | | `27` | Exceeded max notional order amount
Order notional value exceeds the maximum allowed. | | `99` | Other
Reserved for unexpected issues (corrupted side, exponents, or internal identifiers). | | `101` | ***Custom Bitvavo value***
Self-match prevention value is not supported. | | `102` | ***Custom Bitvavo value***
Time in force value is not supported. | | `103` | ***Custom Bitvavo value***
Order or quote quantity exceeds the maximum allowed size. | | `104` | ***Custom Bitvavo value***
Price precision exceeds supported decimals. | | `105` | ***Custom Bitvavo value***
Order or quote quantity is below the minimum allowed size. | | `106` | ***Custom Bitvavo value***
Trigger order type is not supported. | | `107` | ***Custom Bitvavo value***
Trigger price reference is not supported. | | `108` | ***Custom Bitvavo value***
Trigger price precision exceeds supported decimals. | | `109` | ***Custom Bitvavo value***
`ClOrdID` is invalid or duplicated. | | `110` | ***Custom Bitvavo value***
Replace request does not change any order attributes. | | `111` | ***Custom Bitvavo value***
Quantity fields in the replace request conflict with remaining quantity. | | `112` | ***Custom Bitvavo value***
Order notional value is below the minimum allowed. | | `113` | ***Custom Bitvavo value***
Maximum number of orders per market has been reached. | | `114` | ***Custom Bitvavo value***
Price is invalid. | | `115` | ***Custom Bitvavo value***
Bitvavo order identifier is invalid. | | `116` | ***Custom Bitvavo value***
Stop price is invalid. | | `117` | ***Custom Bitvavo value***
Stop price does not align with the market tick size. | | `118` | ***Custom Bitvavo value***
Remaining quantity becomes invalid during processing. | | `119` | ***Custom Bitvavo value***
Market is cancel-only or in auction (collection or matching) mode. | #### ExecRestatementReason values {/* #exec-restatement-reason-values */} We use the standard FIX codes when available. Custom Bitvavo codes start at `101`. | Tag | Description | |:------|:---------------------------------------------------------------------------------| | `6` | Cancel on Trading Halt | | `12` | Cancel On Connection Loss | | `15` | Cancelled, Trade Price Violation | | `17` | Cancelled, self-match prevention | | `101` | ***Custom Bitvavo value***
Decremented, self-match prevention | | `102` | ***Custom Bitvavo value***
Cancelled, placement price protection violation | | `103` | ***Custom Bitvavo value***
Cancelled, spread protection violation | | `104` | ***Custom Bitvavo value***
Cancelled, reference price protection violation | | `105` | ***Custom Bitvavo value***
Cancelled, post-only violation during the auction | | `106` | ***Custom Bitvavo value***
Cancelled, market delisted | | `107` | ***Custom Bitvavo value***
Cancelled, entity lock placed | | `108` | ***Custom Bitvavo value***
Cancelled, admin request | | `109` | ***Custom Bitvavo value***
Cancelled, post-only violation | ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [Order lifecycle](/docs/order-lifecycle/) - [NewOrderSingle](/docs/fix-api/new-order-single/) - [OrderCancelReplaceRequest](/docs/fix-api/order-cancel-replace-request/) - [OrderCancelRequest](/docs/fix-api/order-cancel-request/) - [OrderStatusRequest](/docs/fix-api/order-status-request/) --- ## OrderCancelReject (35=9) Source: https://docs.bitvavo.com/docs/fix-api/order-cancel-reject/ Sent by Bitvavo when your request to cancel or replace an order is rejected. ### Structure Requires: - [Standard header](/docs/fix-api/message-structure/#standard-header) - [Message body](#message) - [Standard trailer](/docs/fix-api/message-structure/#standard-trailer) ### Message body {/* #message */} | Tag | Name | Type | Required | Description | |:--------|:-------------------|:-------------|:---------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------| | `60` | `TransactTime` | UTCTimestamp | N | The UTC timestamp in nanoseconds when the message was created. Must be in the format `YYYYMMDD-HH:MM:SS.sssssssss`, for example `20260115-10:05:54.794327000`. | | `1` | `Account` | String | Y | The unique identifier of the account. | | `2422` | `OrderRequestID` | Int | N | Your unique identifier of the cancel or replace request. | | `37` | `OrderID` | String | Y | Bitvavo identifier of the order. | | `11` | `ClOrdID` | String | Y | Your identifier of the cancel or replace request. | | `41` | `OrigClOrdID` | String | N | Your identifier of the original order. If the order was previously updated, this is the `ClOrdID (11)` of the most recent order. | | `17` | `ExecID` | String | N | Bitvavo identifier of this reject message. | | `39` | `OrdStatus` | Char | Y | The status of the order after this reject is applied. | | `434` | `CxlRejResponseTo` | Char | Y | The type of request that this reject responds to. Can be:
  • `1`: OrderCancelRequest (35=F)
  • `2`: OrderCancelReplaceRequest (35=G)
| | `1328` | `RejectText` | String | N | The description of the reason for rejection. See [Errors](/docs/errors/) for possible values. | | `102` | `CxlRejReason` | Int | N | The reason why the cancel request was rejected.
You can find the possible values [below](#cxl-rej-reason-values). | | `5002` | `OperatorID` | Int | N | ***Custom Bitvavo tag***
Your identifier for the trader or the bot within your account that made the request. | #### CxlRejReason values {/* #cxl-rej-reason-values */} We use standard FIX cancellation rejection tags whenever possible. Codes greater than `100` are custom Bitvavo tags. | Tag | Description | |:------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `1` | Unknown order
The referenced order cannot be located (`OrderNotFound`, `MEOrderNotFound`). | | `8` | Price exceeds current price band
The matching engine rejected the price (`MEOutOfBoundsPlacementPrice`). | | `18` | Invalid price increment
Price does not align with the market tick size (`InvalidPriceTickSize`). | | `99` | Other | | `101` | ***Custom Bitvavo value***
Self-trade prevention instruction is not supported (`InvalidSelfTradePrevention`). | | `102` | ***Custom Bitvavo value***
Time in force value is not supported (`InvalidTimeInForce`). | | `103` | ***Custom Bitvavo value***
Order quantity (base or quote) exceeds the maximum allowed (`InvalidQuantityTooLarge`, `InvalidQuoteQuantityTooLarge`). | | `104` | ***Custom Bitvavo value***
Price precision exceeds supported decimals (`InvalidPricePrecision`). | | `105` | ***Custom Bitvavo value***
Order quantity (base or quote) is below the minimum allowed (`InvalidQuantityTooSmall`, `InvalidQuoteQuantityTooSmall`). | | `106` | ***Custom Bitvavo value***
Trigger order type is not supported (`InvalidTriggerOrderType`). | | `107` | ***Custom Bitvavo value***
Trigger price reference is not supported (`InvalidStopPriceReference`). | | `108` | ***Custom Bitvavo value***
Stop price precision exceeds supported decimals (`InvalidStopPricePrecision`). | | `109` | ***Custom Bitvavo value***
`ClOrdID` is invalid or duplicated (`InvalidClientOrderId`). | | `110` | ***Custom Bitvavo value***
Replace request does not change any order attributes (`UpdateOrderNoChange`). | | `111` | ***Custom Bitvavo value***
Quantity fields in the replace request conflict with remaining quantity (`UpdateOrderInvalidQuantityAndRemainingQuantity`). | | `112` | ***Custom Bitvavo value***
Order notional value is below the minimum allowed (`InvalidNotionalTooSmall`). | | `113` | ***Custom Bitvavo value***
Maximum number of orders per market has been reached (`MaxNumOrdersReached`). | | `114` | ***Custom Bitvavo value***
Price is invalid (`InvalidPrice`). | | `115` | ***Custom Bitvavo value***
Bitvavo order identifier is invalid (`InvalidOrderUuid`). | | `116` | ***Custom Bitvavo value***
Stop price is invalid (`InvalidStopPrice`). | | `117` | ***Custom Bitvavo value***
Stop price does not align with the market tick size (`InvalidStopPriceTickSize`). | | `118` | ***Custom Bitvavo value***
Remaining quantity becomes invalid during processing (`InvalidRemainingQuantity`). | | `119` | ***Custom Bitvavo value***
Market is cancel-only or in auction (collection or matching) mode (`MEInstrumentIsInCancelOnly`, `MEInstrumentIsInAuctionCollection`, `MEInstrumentIsInAuctionMatching`). | | `120` | ***Custom Bitvavo value***
Account cannot be found (`InvalidUserId`). | | `121` | ***Custom Bitvavo value***
Requested market does not exist or cannot be validated (`InvalidInstrument`). | | `122` | ***Custom Bitvavo value***
Quantity fields are malformed or inconsistent (`InvalidQuantity`, `InvalidQuoteQuantity`). | | `123` | ***Custom Bitvavo value***
Account balance cannot cover the order (`InsufficientFunds`). | | `124` | ***Custom Bitvavo value***
Order notional value exceeds the maximum allowed (`InvalidNotionalTooLarge`). | | `125` | ***Custom Bitvavo value***
Instrument is halted (`MEInstrumentIsHalted`). | | `126` | ***Custom Bitvavo value***
Matching engine cannot find the requested instrument (`MEUnknownInstrument`). | ### See also - [Getting started with Bitvavo API](/docs/get-started/) - [Introduction to FIX](/docs/fix-api/introduction/) - [Message structure](/docs/fix-api/message-structure/) - [Errors](/docs/errors/) - [OrderCancelRequest](/docs/fix-api/order-cancel-request/) - [OrderCancelReplaceRequest](/docs/fix-api/order-cancel-replace-request/) - [ExecutionReport](/docs/fix-api/execution-report/) --- ## Frequently asked questions Source: https://docs.bitvavo.com/docs/faqs/ ### Trading
****Are order and cancel requests via WebSocket faster than via REST calls?**** Yes, according to our measurements, WebSocket is faster than REST.
**According to the docs, there's a `TimeInForce` field in the update message. Is it possible to insert a GFD and later amend the `TimeInForce`?** No, it is not possible to amend the `TimeInForce`. We don't have a GFD, its GTC by default.
**Can you please clarify the following transaction types returned by [the transaction history endpoint](/docs/rest-api/get-transaction-history).** The transaction of some types are: - `staking` - rewards that are distributed to users who have opted-in. - `internal_transfer` - used to allow users to move funds between accounts. We no longer log these types of transactions. - `external_transferred_funds` - this is related to Litebit. Users who have their funds transferred over from Litebit will have these types of transactions.
**Do you have any documentation on failure responses for REST or WebSocket requests?** Yes. See our docs about [error handling](/docs/errors).
**How do I request my available euro balance using the API? Should I use the Account balance endpoint with EUR symbol?** Yes! You can use the GET [`/balance`](/docs/rest-api/get-account-balance) request.
**I am trying to connect to Bitvavo and found that rejection messages for the orders do not have any information about which order was rejected.** When you subscribe to an `account` channel and it doesn't have any rejection messages it can be hard to distinguish orders in WebSocket: ```json { "action": "privateCreateOrder", "market": "BTC-EUR", "errorCode": 216, "error": "You do not have sufficient balance to complete this operation." } ``` To counter this, you can add a `requestId` to the request to trace the order.
**Is it possible to increase the rate limit of my API key?** When you are ready for high volume trading, send a request to our Support Team and specify the volume of trading you expect to make. We will be happy to accommodate you. The more you trade, the cheaper it is to trade on Bitvavo. See our market fees [here](https://bitvavo.com/en/fees).
**I would like to understand whether I will see the nonce value reset/decrease during the lifetime of a WebSocket session.** The nonce value should never decrease during the lifetime of a matching engine. However, it is reset when the engine is restarted. This means t hat you can expect that nonce could be reset during the lifetime of WS sessions.
**In trades, there is timestamp (milliseconds). Is it matching engine time?** It’s the time when the trade occurred in UTC.
**Is restarting the matching engine common or a part of a scheduled downtime?** Usually the restart of the matching engine (ME) happens during the scheduled downtime, but tt can happen that something goes wrong and the ME needs to be restarted. See our [Status page](https://status.bitvavo.com/).
**Is there an API endpoint for getting scheduled downtime announcements?** At the moment we don't have such an endpoint.
**My trading bot often incorrectly gives a minimum value error message. How often is this minimum value adjusted to match current market values?** To find the minimum amount for a transaction, make a [Get market data](/docs/rest-api/get-markets) request and use the `minOrderInBaseAsset` and `minOrderInQuoteAsset` values from the response. Then check the value against your balance. For high frequency trading, remember that when you make an order on Bitvavo, the `onHold` amount of the `onHoldCurrency` is blocked. After the trades are completed, there is a slight lag until the trading fees are charged.
**What is an `operatorId`?** `operatorId` is an integer that you specify to identify the trader or algorithm responsible for each order submitted using your API integration. It enables clearer attribution of trading activity, which is critical for compliance and auditability.
**What action do I need to take regarding `operatorId`?** If you use the Bitvavo Mobile or Web App **no action is required**. If you use the Bitvavo API to place orders, you need to include this field in all create, update, and cancel order requests made through either the REST or WebSocket APIs. Otherwise, requests without an `operatorId` will be rejected.
**How should I assign `operatorId`?** You can assign a unique integer identifier to each trader or trading algorithm that places orders in your account. For example: - Human traders: Alice = 1001, Bob = 1002. - Trading algorithms: "Strategy A" = 2001, "Bot X" = 2002. You are free to define and manage the identifiers for your account, but they must be unique and consistent within your account.
**What is the format of the `operatorId`?** The field must be an integer. For example: - **Valid**: 1,1001, 2000000000, 999999 - **Invalid**: "trader-1" (string), 12.5 (float), null
**Can I test the `operatorId`?** Yes. The `operatorId` parameter is already supported in our API. We recommend you to update and test your integration.
**What API requests require the `operatorId` parameter?** **REST API**: - [Create Order](/docs/rest-api/create-order/) - [Update Order](/docs/rest-api/update-order/) - [Cancel Order](/docs/rest-api/cancel-order/) - [Cancel Orders](/docs/rest-api/cancel-orders/) **WebSocket API**: - [Create Order](/docs/websocket-api/create-order/) - [Update Order](/docs/websocket-api/update-order/) - [Cancel Order](/docs/websocket-api/cancel-order/) - [Cancel Orders](/docs/websocket-api/cancel-orders/)
**Why can the ticker price stay unchanged for a period of time while the historical price continues to fluctuate?** The ticker price shows the last executed trade. If no trades occur, it remains unchanged. Historical prices (candles) use fixed time intervals and can change even without new trades. This happens because updates in the order book affect how these values are calculated. This behavior is more common in illiquid markets, where trades occur less frequently. Trades execute against the order book, not the ticker price. The relevant prices are the best bid (highest buy) and best ask (lowest sell), which update in real time. Use the [ticker endpoint](/docs/rest-api/get-ticker-prices) to get the last traded price, and the [order book endpoint](/docs/rest-api/get-order-book) to get current bid and ask prices.
**What is pre-trade and post-trade transparency?** To comply with the *Markets in Crypto-Assets Regulation (MiCA)*, Bitvavo provides pre-trade and post-trade transparency data for crypto-asset markets through our REST API. The **Pre-trade transparency** includes the aggregated order book data with the bid and ask prices, the depth of trading interest at those prices, and the total number of orders. To retrieve it, make a [Get order book report](/docs/rest-api/get-order-book-report/) request. The **Post-trade transparency** includes the data about all executed transactions on the Bitvavo trading platform with the price, volume, timestamp, and the crypto assets. To retrieve it, make a [Get trades report](/docs/rest-api/get-trades-report/) request.
### WebSocket
**Are the response samples in the API docs the same for Websocket responses?** Yes, the returned parameters are the same for WebSocket and REST APIs. However, the response structure differs due to the difference in protocols. For example, WebSocket responses wrap the data in an `action` and `response` object, while REST returns the data directly.
**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? It is the expected behavior that all clients receive the same updates.
**Can I rely on a deterministic ordering of fill and order events? For example, when a fill occurs on Bitvavo, does a WebSocket session see an order, then fill event (or vice versa)? Will this ordering always be consistent?** 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.
**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?** WS will stay connected. WS can be used for different markets and actions.
**Is it delta update for the full book for WebSocket book subscription or is it limited to some range?** We don't limit the depth for the order book event, we handle the event as we get it from a matching engine (ME).
**Is it guaranteed that a fill-event from the WebSocket trading subscription will be received only after a response for **createOrder** event?** 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.
**Is it possible for a fill event to be faster than order event?** 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.
**Is there any benefit to authenticating WebSocket connections used for receiving market data events?** Yes. If you exceed the [rate limit](/docs/rate-limits), authenticated users are blocked for **1 minute**, while unauthenticated users are blocked for **15 minutes**.
**Is there any speed advantage when using an authenticated WebSocket connection if I only use endpoints that don't require authentication.** No, there is no speed advantage. But authenticated users are blocked for a shorter period if the [rate limit](/docs/rate-limits) is exceeded (**1 minute** vs **15 minutes** for unauthenticated users).
**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`** 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.
**What is the behavior 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?** WebSocket(WS) is built on top of TCP. All packets are delivered in order and there's checks for packet loss. The server can buffer messages to a point, but 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.
**What is the maximum number of Websocket connections one account can open?** We don't have a limit in place but the rate limit is shared between all open connections.
**When I subscribe to messages using WebSocket, do I need to do that via a REST call? Is it also possible to send a subscription message directly over the WebSocket?** WebSocket protocol works over HTTP. You need to open a WebSocket connection and send the request with actions that you want. See the [WebSocket](/docs/websocket-api) docs. You could also use one of our [SDKs](https://github.com/bitvavo).
### Withdrawals
**Is it possible to transfer transaction costs in euros internally via the API? So from one Bitvavo user to another Bitvavo user?** Unfortunately, this is not possible. You can only transfer digital assets between internal wallets. Euro transactions are sent to your IBAN which is external to Bitvavo. Fees for any transaction on Bitvavo are charged just after the operation has taken place. For example, after a trade takes place or a is transaction made. In the case of asset withdrawal, see the `internal` and `addWithdrawalFee` parameter in [POST methods](/docs/rest-api/withdraw-assets).
**I 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 on Bitvavo are also not possible.Is there a way to facilitate internal transfers without disabling this lock?** 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.
**Withdrawals of digital coins, both internally and externally, can only take place if a crypto address has been added to the address book. How does that work with an internal transfer, from one Bitvavo user to another?** You should set the wallet address in POST [`/withdrawal`](/docs/rest-api/withdraw-assets).
### Rate limits
**Is there a weight difference in a WebSocket subscription request if I subscribe to multiple markets in a single request?** No. The difference in the request composition is only for ticker24 and open orders. They are more expensive if no market is specified.
**What is the weight of a WebSocket subscription request and is it different per subscription? Does the `OrderBook` have a different weight from `Ticker` or `Trades`?** No, they all have the default point. You can find the exact weight of each request in the API docs.
--- ## Releases Source: https://docs.bitvavo.com/releases/ Individual release notes are listed at https://docs.bitvavo.com/releases/. They are intentionally omitted from this file; fetch the page directly when you need the changelog. --- ## API specification Source: https://docs.bitvavo.com/llms.txt The machine-readable specs are downloadable at: - [exchange-rest-api.yaml](https://docs.bitvavo.com/api-specs/exchange-rest-api.yaml) - [exchange-websocket-api.yaml](https://docs.bitvavo.com/api-specs/exchange-websocket-api.yaml) - [ws-market-data-pro-api.yaml](https://docs.bitvavo.com/api-specs/ws-market-data-pro-api.yaml) - [institutional-api.yaml](https://docs.bitvavo.com/api-specs/institutional-api.yaml) - [2026-04-28.fix.xml](https://docs.bitvavo.com/api-specs/2026-04-28.fix.xml)