Skip to main content

Introduction

Learn how to authenticate your requests to Bitvavo REST API. For the API reference, see REST API.

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.