Skip to main content

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 with the following HTTP headers in every request to Bitvavo REST API:

  • Bitvavo-Access-Key (required): an API Key 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 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:
    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:
    Example API secret
    bitvavo
  4. Using your API secret, encode the concatenated string to HMAC-SHA256:
    Signature encoded with the Example API secret
    44d022723a20973a18f7ee97398b9fdd405d2d019c8d39e24b8cc0dcb39ca016

Python example​

Below is a Python code sample on how to sign a Create order request:

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:

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, 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 in your Bitvavo dashboard.

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.