bitstamp_api_docs.md 25 KB

Bitstamp HTTP API v2 — Python Reference

Base URL: https://www.bitstamp.net
Official docs: https://www.bitstamp.net/api/


Table of Contents

  1. Overview
  2. Rate Limits
  3. Authentication
  4. HTTP Status Codes & Error Codes
  5. Public Endpoints
  6. Private Endpoints
  7. Python Examples

Overview

The Bitstamp API allows clients to access and control their accounts using custom software. All responses are JSON. Private endpoints require authentication via HMAC-SHA256 signed headers.


Rate Limits

Limit Value
Requests per second 400
Default threshold 10,000 requests per 10 minutes

Rate limits can be increased by contacting Bitstamp. For real-time data, use the WebSocket API instead of polling REST endpoints.


Authentication

All private API calls require the following HTTP headers:

Header Value
X-Auth "BITSTAMP " + api_key
X-Auth-Signature HMAC-SHA256 signature (hex string)
X-Auth-Nonce UUID4 string (lowercase, 36 chars, unique per request, valid for 150 seconds)
X-Auth-Timestamp Request departure time — UTC milliseconds
X-Auth-Version "v2"
Content-Type "application/x-www-form-urlencoded" (omit if request body is empty)

Signature Construction

The string to sign is constructed by concatenating (with no separators):

"BITSTAMP " + api_key
+ HTTP_METHOD          (e.g. "POST" or "GET")
+ "www.bitstamp.net"
+ URL_PATH             (e.g. "/api/v2/balance/")
+ QUERY_STRING         (empty string if none)
+ CONTENT_TYPE         (empty string if no body)
+ NONCE
+ TIMESTAMP
+ "v2"
+ PAYLOAD_STRING       (URL-encoded body, empty string if none)

Important: If the request body is empty, omit Content-Type from both the headers and the signature string.

Python Authentication Example

import hashlib
import hmac
import time
import uuid
import requests
from urllib.parse import urlencode

API_KEY = 'your_api_key'
API_SECRET = b'your_api_secret'

def build_headers(method, path, payload=None, query=''):
    timestamp = str(int(round(time.time() * 1000)))
    nonce = str(uuid.uuid4())

    if payload:
        payload_string = urlencode(payload)
        content_type = 'application/x-www-form-urlencoded'
    else:
        payload_string = ''
        content_type = ''

    message = (
        'BITSTAMP ' + API_KEY
        + method
        + 'www.bitstamp.net'
        + path
        + query
        + content_type
        + nonce
        + timestamp
        + 'v2'
        + payload_string
    ).encode('utf-8')

    signature = hmac.new(API_SECRET, msg=message, digestmod=hashlib.sha256).hexdigest()

    headers = {
        'X-Auth': 'BITSTAMP ' + API_KEY,
        'X-Auth-Signature': signature,
        'X-Auth-Nonce': nonce,
        'X-Auth-Timestamp': timestamp,
        'X-Auth-Version': 'v2',
    }
    if content_type:
        headers['Content-Type'] = content_type

    return headers, payload_string


def private_post(path, payload=None):
    headers, body = build_headers('POST', path, payload)
    url = 'https://www.bitstamp.net' + path
    response = requests.post(url, headers=headers, data=body)
    return response.json()


def private_get(path, query=''):
    headers, _ = build_headers('GET', path, query=query)
    url = 'https://www.bitstamp.net' + path
    if query:
        url += '?' + query
    response = requests.get(url, headers=headers)
    return response.json()

HTTP Status Codes & Error Codes

HTTP Status Codes

Code Meaning
200 OK
400 Bad Request — invalid parameters
401 Unauthorized — authentication failed
403 Forbidden — insufficient permissions
404 Not Found
429 Too Many Requests — rate limit exceeded
500 Internal Server Error

API Response Codes (selected)

Errors may include a response_code field (e.g. "400.001") and optional response_explanation:

Code Description
400.001 Unknown validation error
400.002 Rate limit exceeded
API0020 Content-Type header should not be present (on empty-body requests)
API5012 Returned on certain earn endpoint errors

Public Endpoints

Public endpoints require no authentication.


Currencies

GET /api/v2/currencies/

Returns a list of all listed currencies with basic info, including supported blockchain networks, minimum withdrawal amounts, deposit/withdrawal status, and decimal precision per network.

import requests

response = requests.get('https://www.bitstamp.net/api/v2/currencies/')
currencies = response.json()

Markets

GET /api/v2/markets/

Returns info about all available trading markets/pairs. Replaces the deprecated /api/v2/trading-pairs-info/.

response = requests.get('https://www.bitstamp.net/api/v2/markets/')
markets = response.json()

Ticker

GET /api/v2/ticker/

Returns ticker data for all markets. Do not pass any GET parameters.

GET /api/v2/ticker/{market_symbol}/

Returns ticker data for a specific currency pair (e.g. btcusd, ethusd, ethbtc).

Response fields:

Field Description
last Last traded price
high 24-hour high
low 24-hour low
bid Highest buy order
ask Lowest sell order
volume 24-hour volume
vwap 24-hour volume weighted average price
open Opening price
timestamp Unix timestamp
response = requests.get('https://www.bitstamp.net/api/v2/ticker/btcusd/')
ticker = response.json()
print(ticker['last'], ticker['bid'], ticker['ask'])

GET /api/v2/ticker_hour/{market_symbol}/

Returns hourly ticker data (values computed over the past hour) for a currency pair.

response = requests.get('https://www.bitstamp.net/api/v2/ticker_hour/btcusd/')

Order Book

GET /api/v2/order_book/{market_symbol}/

Returns the current order book for a market.

Query parameters:

Parameter Type Description
group int 0 = ungrouped, 1 = group by price (default), 2 = group by price, include order count

Response fields:

Field Description
timestamp Unix timestamp
microtimestamp Microsecond timestamp
bids List of [price, amount] arrays (descending by price)
asks List of [price, amount] arrays (ascending by price)
response = requests.get('https://www.bitstamp.net/api/v2/order_book/btcusd/')
order_book = response.json()
best_bid = order_book['bids'][0]
best_ask = order_book['asks'][0]

Transactions

GET /api/v2/transactions/{market_symbol}/

Returns recent public trades for a market.

Query parameters:

Parameter Type Default Description
time string hour Time window: minute, hour, or day

Response fields (per trade):

Field Description
date Unix timestamp
tid Trade ID
price Trade price
amount Trade amount
type 0 = buy, 1 = sell
response = requests.get(
    'https://www.bitstamp.net/api/v2/transactions/btcusd/',
    params={'time': 'hour'}
)
trades = response.json()

OHLC (Candlestick Data)

GET /api/v2/ohlc/{market_symbol}/

Returns OHLCV candlestick data.

Query parameters:

Parameter Type Required Description
step int Yes Candle duration in seconds. Valid values: 60, 180, 300, 900, 1800, 3600, 7200, 14400, 21600, 43200, 86400, 259200
limit int Yes Number of candles to return (1–1000)
start int No Start Unix timestamp
end int No End Unix timestamp
exclude_current_candle bool No Exclude the still-open current candle

Response structure:

{
  "data": {
    "pair": "BTC/USD",
    "ohlc": [
      {
        "timestamp": "1609459200",
        "open": "28999.63",
        "high": "29022.01",
        "low": "28999.14",
        "close": "29006.31",
        "volume": "0.86157958"
      }
    ]
  }
}
import requests
import pandas as pd

currency_pair = 'btcusd'
url = f'https://www.bitstamp.net/api/v2/ohlc/{currency_pair}/'

params = {
    'step': 3600,    # 1-hour candles
    'limit': 100,
}

response = requests.get(url, params=params)
ohlc_data = response.json()['data']['ohlc']

df = pd.DataFrame(ohlc_data)
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='s')
df[['open', 'high', 'low', 'close', 'volume']] = df[['open', 'high', 'low', 'close', 'volume']].astype(float)
print(df.tail())

Fetching historical OHLC in date ranges:

import requests
import pandas as pd

currency_pair = 'btcusd'
url = f'https://www.bitstamp.net/api/v2/ohlc/{currency_pair}/'

start = '2021-01-01'
end   = '2021-01-02'

dates = pd.date_range(start, end, freq='6H')
dates = [int(x.value / 10**9) for x in list(dates)]

master_data = []
for first, last in zip(dates, dates[1:]):
    params = {'step': 60, 'limit': 1000, 'start': first, 'end': last}
    data = requests.get(url, params=params).json()['data']['ohlc']
    master_data += data

df = pd.DataFrame(master_data)

EUR/USD Conversion Rate

GET /api/v2/eur_usd/

Returns the current EUR/USD conversion rate.

Response fields:

Field Description
buy Conversion rate for buying
sell Conversion rate for selling
response = requests.get('https://www.bitstamp.net/api/v2/eur_usd/')
rate = response.json()

Travel Rule VASPs

GET /api/v2/travel-rule/vasps/

Returns a list of Virtual Asset Service Providers (VASPs) required for Travel Rule compliance when transferring crypto to/from other platforms.

response = requests.get('https://www.bitstamp.net/api/v2/travel-rule/vasps/')
vasps = response.json()

Private Endpoints

All private endpoints require authentication headers (see Authentication).


Account Balances

POST /api/v2/account_balances/

Returns all account balances across all currencies.

Response fields (per currency, e.g. btc_):

Field Description
{currency}_balance Total balance
{currency}_available Available (not reserved)
{currency}_reserved Reserved in open orders
balances = private_post('/api/v2/account_balances/')
btc_available = balances.get('btc_available')
usd_available = balances.get('usd_available')

POST /api/v2/account_balances/{currency}/

Returns balances for a specific currency.

btc_balance = private_post('/api/v2/account_balances/btc/')

Fees

POST /api/v2/fees/trading/

Returns all trading fees.

POST /api/v2/fees/trading/{market_symbol}/

Returns trading fees for a specific market.

POST /api/v2/fees/withdrawal/

Returns all withdrawal fees.

POST /api/v2/fees/withdrawal/{currency}/

Returns withdrawal fee for a specific currency.

fees = private_post('/api/v2/fees/trading/')
btcusd_fee = private_post('/api/v2/fees/trading/btcusd/')
withdrawal_fees = private_post('/api/v2/fees/withdrawal/')

Orders

POST /api/v2/order_status/

Returns the status of an order. Works for the account (sub or main) the API key is bound to. For closed orders, only data from the past 30 days is available.

Parameters:

Parameter Type Description
id string Order ID (use either this or client_order_id)
client_order_id string Client-assigned order ID
status = private_post('/api/v2/order_status/', {'id': '1234567890'})

POST /api/v2/open_orders/all/

Returns all open orders across all markets. Cached for 10 seconds.

open_orders = private_post('/api/v2/open_orders/all/')

POST /api/v2/open_orders/{market_symbol}/

Returns open orders for a specific market.

open_orders = private_post('/api/v2/open_orders/btcusd/')

Open order response fields:

Field Description
id Order ID
client_order_id Client-specified ID (if provided)
datetime Order creation datetime
type 0 = buy, 1 = sell
price Order price
amount Remaining amount
market Market symbol

POST /api/v2/cancel_order/

Cancels an order.

Parameters:

Parameter Type Description
id string Order ID to cancel

Response: May include "status": "Canceled" or "status": "Cancel pending" (if a duplicate cancel is in progress; HTTP 200 is still returned).

result = private_post('/api/v2/cancel_order/', {'id': '1234567890'})

POST /api/v2/cancel_all_orders/

Cancels all open orders.

result = private_post('/api/v2/cancel_all_orders/')

POST /api/v2/cancel_all_orders/{market_symbol}/

Cancels all open orders for a specific market.

result = private_post('/api/v2/cancel_all_orders/btcusd/')

POST /api/v2/buy/{market_symbol}/

Places a limit buy order.

Parameters:

Parameter Type Required Description
amount decimal string Yes Amount to buy
price decimal string Yes Limit price
limit_price decimal string No If set, order becomes a stop-limit buy
daily_order bool No Order expires at end of day (UTC midnight) if true
ioc_order bool No Immediate-or-cancel order
client_order_id string No Custom order identifier
order = private_post('/api/v2/buy/btcusd/', {
    'amount': '0.001',
    'price': '30000.00',
})

POST /api/v2/buy/market/{market_symbol}/

Places a market buy order.

Parameters:

Parameter Type Required Description
amount decimal string Yes Amount of quote currency to spend
client_order_id string No Custom order identifier
order = private_post('/api/v2/buy/market/btcusd/', {'amount': '100.00'})

POST /api/v2/buy/instant/{market_symbol}/

Places an instant buy order (fills at current market price against the order book).

Parameters: Same as market order.

POST /api/v2/sell/{market_symbol}/

Places a limit sell order.

Parameters: Same as limit buy.

order = private_post('/api/v2/sell/btcusd/', {
    'amount': '0.001',
    'price': '50000.00',
})

POST /api/v2/sell/market/{market_symbol}/

Places a market sell order.

Parameters:

Parameter Type Required Description
amount decimal string Yes Amount of base currency to sell
client_order_id string No Custom order identifier
order = private_post('/api/v2/sell/market/btcusd/', {'amount': '0.001'})

POST /api/v2/sell/instant/{market_symbol}/

Places an instant sell order.

POST /api/v2/replace_order/

Replaces an existing order (cancel + new order atomically).

Parameters: id of the order to replace, plus the standard order creation parameters.

POST /api/v2/order_data/

Retrieves historical public order events for a market (for WebSocket gap recovery).

POST /api/v2/account_order_data/

Retrieves historical order events for the authenticated user's account (for WebSocket gap recovery).

Order response fields:

Field Description
id Order ID
client_order_id Client-assigned ID
datetime Datetime string
type 0 = buy, 1 = sell
price Order price
amount Order amount
market Market symbol
status Order status

User Transactions

POST /api/v2/user_transactions/

Returns transaction history for the account.

Parameters:

Parameter Type Default Description
offset int 0 Number of transactions to skip
limit int 100 Number of transactions to return
sort string desc Sort order: asc or desc
since_timestamp int Return only transactions after this Unix timestamp
since_id int Return only transactions after this transaction ID

Transaction types:

Value Description
0 Deposit
1 Withdrawal
2 Market trade
14 Sub account transfer
25 Credited with staked assets
26 Sent assets to staking
27 Staking reward
32 Referral reward
35 Inter-account transfer
transactions = private_post('/api/v2/user_transactions/', {
    'offset': '0',
    'limit': '100',
    'sort': 'desc',
})

POST /api/v2/user_transactions/{market_symbol}/

Returns transactions filtered to a specific market.

transactions = private_post('/api/v2/user_transactions/btcusd/', {
    'limit': '50',
    'sort': 'desc',
})

Crypto Deposits

POST /api/v2/crypto-transactions/deposits/

Returns crypto deposit transaction history.

POST /api/v2/crypto-transactions/deposits/{deposit_id}/reject/

Rejects a specific crypto deposit.

POST /api/v2/{currency}_address/

Returns (or generates) the deposit address for a given cryptocurrency.

Available address endpoints include:

  • POST /api/v2/btc_address/
  • POST /api/v2/eth_address/
  • POST /api/v2/ltc_address/
  • POST /api/v2/xrp_address/
  • POST /api/v2/bch_address/
  • POST /api/v2/xlm_address/
  • POST /api/v2/pax_address/
  • POST /api/v2/link_address/
  • POST /api/v2/omg_address/
  • POST /api/v2/usdc_address/

    btc_address = private_post('/api/v2/btc_address/')
    eth_address = private_post('/api/v2/eth_address/')
    

Crypto Withdrawals

POST /api/v2/crypto-transactions/withdrawals/

Returns crypto withdrawal transaction history.

POST /api/v2/btc_withdrawal/

Withdraw Bitcoin.

Parameters:

Parameter Type Required Description
amount decimal string Yes Amount in BTC
address string Yes Bitcoin address
instant int No 1 for instant, 0 for standard
result = private_post('/api/v2/btc_withdrawal/', {
    'amount': '0.001',
    'address': 'bc1q...',
})

POST /api/v2/eth_withdrawal/

Withdraw Ethereum.

Parameters: amount and address.

result = private_post('/api/v2/eth_withdrawal/', {
    'amount': '0.01',
    'address': '0x...',
})

Similar endpoints exist for other currencies (e.g. ltc_withdrawal, xrp_withdrawal, bch_withdrawal, xlm_withdrawal, usdc_withdrawal, etc.).

Note: Travel Rule data fields are optional now but will become mandatory in a future breaking change.


Bank Withdrawals

POST /api/v2/withdrawal/open/

Opens a bank (fiat) withdrawal.

Common parameters (see official docs for full field list by withdrawal type):

Parameter Description
amount Withdrawal amount
account_currency Currency (e.g. USD, EUR)
name Account holder name
bank_name Receiving bank name
iban IBAN (for SEPA transfers)
bic BIC/SWIFT code
address Account holder address
city City
country Country code
result = private_post('/api/v2/withdrawal/open/', {
    'amount': '100.00',
    'account_currency': 'EUR',
    'name': 'John Doe',
    'iban': 'DE89...',
    'bic': 'COBADEFFXXX',
    'address': '123 Main St',
    'city': 'Berlin',
    'country': 'DE',
})

POST /api/v2/withdrawal/status/

Returns the status of a withdrawal.

Parameters: id — withdrawal ID.

POST /api/v2/withdrawal/cancel/

Cancels a pending bank withdrawal.

Parameters: id — withdrawal ID.


Withdrawal Requests

POST /api/v2/withdrawal-requests/

Returns a list of all withdrawal requests.

Parameters:

Parameter Type Default Description
timedelta int 86400 Return requests within this many seconds of now

Response fields (per request):

Field Description
id Withdrawal ID
datetime Datetime string
type Withdrawal type (0=SEPA, 1=Bitcoin, 2=Wire, etc.)
status 0=Open, 1=In process, 2=Finished, 3=Cancelled, 4=Failed
amount Amount
data Extra type-specific data
requests_list = private_post('/api/v2/withdrawal-requests/', {'timedelta': '86400'})

API Key Management

POST /api/v2/api-key/revoke/all/

Revokes all API keys for the account (kill switch). Use with extreme caution.

result = private_post('/api/v2/api-key/revoke/all/')

Python Examples

Public: Fetch Ticker

import requests

def get_ticker(pair='btcusd'):
    url = f'https://www.bitstamp.net/api/v2/ticker/{pair}/'
    response = requests.get(url)
    response.raise_for_status()
    return response.json()

ticker = get_ticker('ethusd')
print(f"ETH/USD last: {ticker['last']}, bid: {ticker['bid']}, ask: {ticker['ask']}")

Public: Fetch Order Book

import requests

def get_order_book(pair='btcusd', group=1):
    url = f'https://www.bitstamp.net/api/v2/order_book/{pair}/'
    response = requests.get(url, params={'group': group})
    response.raise_for_status()
    return response.json()

book = get_order_book('btcusd')
print("Best bid:", book['bids'][0])
print("Best ask:", book['asks'][0])

Public: Fetch OHLC Data into DataFrame

import requests
import pandas as pd

def get_ohlc(pair='btcusd', step=3600, limit=100):
    url = f'https://www.bitstamp.net/api/v2/ohlc/{pair}/'
    response = requests.get(url, params={'step': step, 'limit': limit})
    response.raise_for_status()
    data = response.json()['data']['ohlc']
    df = pd.DataFrame(data)
    df['timestamp'] = pd.to_datetime(df['timestamp'], unit='s')
    numeric_cols = ['open', 'high', 'low', 'close', 'volume']
    df[numeric_cols] = df[numeric_cols].astype(float)
    return df.set_index('timestamp')

df = get_ohlc('btcusd', step=86400, limit=30)  # 30 daily candles
print(df.tail())

Private: Full Authentication & Balance Check

import hashlib
import hmac
import time
import uuid
import requests
from urllib.parse import urlencode

API_KEY = 'your_api_key'
API_SECRET = b'your_api_secret'

def signed_post(path, payload=None):
    timestamp = str(int(round(time.time() * 1000)))
    nonce = str(uuid.uuid4())

    if payload:
        payload_string = urlencode(payload)
        content_type = 'application/x-www-form-urlencoded'
    else:
        payload_string = ''
        content_type = ''

    message = (
        'BITSTAMP ' + API_KEY
        + 'POST'
        + 'www.bitstamp.net'
        + path
        + ''           # query string (empty for POST)
        + content_type
        + nonce
        + timestamp
        + 'v2'
        + payload_string
    ).encode('utf-8')

    signature = hmac.new(API_SECRET, msg=message, digestmod=hashlib.sha256).hexdigest()

    headers = {
        'X-Auth': 'BITSTAMP ' + API_KEY,
        'X-Auth-Signature': signature,
        'X-Auth-Nonce': nonce,
        'X-Auth-Timestamp': timestamp,
        'X-Auth-Version': 'v2',
    }
    if content_type:
        headers['Content-Type'] = content_type

    url = 'https://www.bitstamp.net' + path
    response = requests.post(url, headers=headers, data=payload_string)
    response.raise_for_status()
    return response.json()

# Get all balances
balances = signed_post('/api/v2/account_balances/')
print(f"BTC available: {balances.get('btc_available')}")
print(f"USD available: {balances.get('usd_available')}")

Private: Place a Limit Buy Order

order = signed_post('/api/v2/buy/btcusd/', {
    'amount': '0.0001',
    'price': '25000.00',
})
print("Order placed:", order)

Private: Get Open Orders & Cancel All

# List open orders
open_orders = signed_post('/api/v2/open_orders/all/')
print(f"Open orders: {len(open_orders)}")

# Cancel all open orders
result = signed_post('/api/v2/cancel_all_orders/')
print("Cancel result:", result)

Private: User Transaction History

transactions = signed_post('/api/v2/user_transactions/', {
    'offset': '0',
    'limit': '50',
    'sort': 'desc',
})

for tx in transactions:
    tx_type = {0: 'Deposit', 1: 'Withdrawal', 2: 'Trade'}.get(int(tx['type']), str(tx['type']))
    print(f"{tx['datetime']} | {tx_type} | {tx.get('btc', '')} BTC | {tx.get('usd', '')} USD")

This document is compiled from the official Bitstamp API documentation at https://www.bitstamp.net/api/ and is Python-focused. Always refer to the official docs for the most up-to-date endpoint parameters and response schemas.