|
|
@@ -0,0 +1,1047 @@
|
|
|
+# Bitstamp HTTP API v2 — Python Reference
|
|
|
+
|
|
|
+> **Base URL:** `https://www.bitstamp.net`
|
|
|
+> **Official docs:** https://www.bitstamp.net/api/
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Table of Contents
|
|
|
+
|
|
|
+1. [Overview](#overview)
|
|
|
+2. [Rate Limits](#rate-limits)
|
|
|
+3. [Authentication](#authentication)
|
|
|
+4. [HTTP Status Codes & Error Codes](#http-status-codes--error-codes)
|
|
|
+5. [Public Endpoints](#public-endpoints)
|
|
|
+ - [Currencies](#currencies)
|
|
|
+ - [Markets](#markets)
|
|
|
+ - [Ticker](#ticker)
|
|
|
+ - [Order Book](#order-book)
|
|
|
+ - [Transactions](#transactions)
|
|
|
+ - [OHLC (Candlestick Data)](#ohlc-candlestick-data)
|
|
|
+ - [EUR/USD Conversion Rate](#eurusd-conversion-rate)
|
|
|
+ - [Travel Rule VASPs](#travel-rule-vasps)
|
|
|
+6. [Private Endpoints](#private-endpoints)
|
|
|
+ - [Account Balances](#account-balances)
|
|
|
+ - [Fees](#fees)
|
|
|
+ - [Orders](#orders)
|
|
|
+ - [User Transactions](#user-transactions)
|
|
|
+ - [Crypto Deposits](#crypto-deposits)
|
|
|
+ - [Crypto Withdrawals](#crypto-withdrawals)
|
|
|
+ - [Bank Withdrawals](#bank-withdrawals)
|
|
|
+ - [Withdrawal Requests](#withdrawal-requests)
|
|
|
+ - [API Key Management](#api-key-management)
|
|
|
+7. [Python Examples](#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
|
|
|
+
|
|
|
+```python
|
|
|
+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.
|
|
|
+
|
|
|
+```python
|
|
|
+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/`.
|
|
|
+
|
|
|
+```python
|
|
|
+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 |
|
|
|
+
|
|
|
+```python
|
|
|
+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.
|
|
|
+
|
|
|
+```python
|
|
|
+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) |
|
|
|
+
|
|
|
+```python
|
|
|
+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 |
|
|
|
+
|
|
|
+```python
|
|
|
+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:**
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "data": {
|
|
|
+ "pair": "BTC/USD",
|
|
|
+ "ohlc": [
|
|
|
+ {
|
|
|
+ "timestamp": "1609459200",
|
|
|
+ "open": "28999.63",
|
|
|
+ "high": "29022.01",
|
|
|
+ "low": "28999.14",
|
|
|
+ "close": "29006.31",
|
|
|
+ "volume": "0.86157958"
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```python
|
|
|
+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:**
|
|
|
+
|
|
|
+```python
|
|
|
+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 |
|
|
|
+
|
|
|
+```python
|
|
|
+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.
|
|
|
+
|
|
|
+```python
|
|
|
+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](#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 |
|
|
|
+
|
|
|
+```python
|
|
|
+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.
|
|
|
+
|
|
|
+```python
|
|
|
+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.
|
|
|
+
|
|
|
+```python
|
|
|
+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 |
|
|
|
+
|
|
|
+```python
|
|
|
+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.
|
|
|
+
|
|
|
+```python
|
|
|
+open_orders = private_post('/api/v2/open_orders/all/')
|
|
|
+```
|
|
|
+
|
|
|
+#### `POST /api/v2/open_orders/{market_symbol}/`
|
|
|
+
|
|
|
+Returns open orders for a specific market.
|
|
|
+
|
|
|
+```python
|
|
|
+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).
|
|
|
+
|
|
|
+```python
|
|
|
+result = private_post('/api/v2/cancel_order/', {'id': '1234567890'})
|
|
|
+```
|
|
|
+
|
|
|
+#### `POST /api/v2/cancel_all_orders/`
|
|
|
+
|
|
|
+Cancels all open orders.
|
|
|
+
|
|
|
+```python
|
|
|
+result = private_post('/api/v2/cancel_all_orders/')
|
|
|
+```
|
|
|
+
|
|
|
+#### `POST /api/v2/cancel_all_orders/{market_symbol}/`
|
|
|
+
|
|
|
+Cancels all open orders for a specific market.
|
|
|
+
|
|
|
+```python
|
|
|
+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 |
|
|
|
+
|
|
|
+```python
|
|
|
+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 |
|
|
|
+
|
|
|
+```python
|
|
|
+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.
|
|
|
+
|
|
|
+```python
|
|
|
+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 |
|
|
|
+
|
|
|
+```python
|
|
|
+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 |
|
|
|
+
|
|
|
+```python
|
|
|
+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.
|
|
|
+
|
|
|
+```python
|
|
|
+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/`
|
|
|
+
|
|
|
+```python
|
|
|
+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 |
|
|
|
+
|
|
|
+```python
|
|
|
+result = private_post('/api/v2/btc_withdrawal/', {
|
|
|
+ 'amount': '0.001',
|
|
|
+ 'address': 'bc1q...',
|
|
|
+})
|
|
|
+```
|
|
|
+
|
|
|
+#### `POST /api/v2/eth_withdrawal/`
|
|
|
+
|
|
|
+Withdraw Ethereum.
|
|
|
+
|
|
|
+**Parameters:** `amount` and `address`.
|
|
|
+
|
|
|
+```python
|
|
|
+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 |
|
|
|
+
|
|
|
+```python
|
|
|
+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 |
|
|
|
+
|
|
|
+```python
|
|
|
+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.
|
|
|
+
|
|
|
+```python
|
|
|
+result = private_post('/api/v2/api-key/revoke/all/')
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Python Examples
|
|
|
+
|
|
|
+### Public: Fetch Ticker
|
|
|
+
|
|
|
+```python
|
|
|
+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
|
|
|
+
|
|
|
+```python
|
|
|
+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
|
|
|
+
|
|
|
+```python
|
|
|
+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
|
|
|
+
|
|
|
+```python
|
|
|
+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
|
|
|
+
|
|
|
+```python
|
|
|
+order = signed_post('/api/v2/buy/btcusd/', {
|
|
|
+ 'amount': '0.0001',
|
|
|
+ 'price': '25000.00',
|
|
|
+})
|
|
|
+print("Order placed:", order)
|
|
|
+```
|
|
|
+
|
|
|
+### Private: Get Open Orders & Cancel All
|
|
|
+
|
|
|
+```python
|
|
|
+# 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
|
|
|
+
|
|
|
+```python
|
|
|
+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.*
|