OAuth 2.0 API Reference
Authentication
OAuth 2.0 Authorization
Example Request:
https://whitebit.com/auth/login?clientId=YOUR_CLIENT_ID&state=SECURE_RANDOM_STATE
This endpoint initiates the OAuth 2.0 authorization flow for user authentication and obtaining an authorization code.
Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
clientId | string | Yes | Your application’s client ID |
state | string | Recommended | A secure random string used to maintain state between the request and callback and prevent CSRF attacks |
Using the State Parameter (Best Practice)
The state
parameter is crucial for security in OAuth flows:
import crypto from 'crypto';
import http from 'http';
import https from 'https';
import { URL, URLSearchParams } from 'url';
import { parse as parseUrl } from 'url';
import { parse as parseQueryString } from 'querystring';
// Simple in-memory session store (for production use a proper store)
const sessions = new Map<string, Record<string, any>>();
// Generate a secure random state value
function generateSecureState(): string {
return crypto.randomBytes(32)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
}
// Generate session ID
function generateSessionId(): string {
return crypto.randomBytes(16).toString('hex');
}
// Create HTTP server
const server = http.createServer((req, res) => {
// Get or create session
let sessionId = '';
const cookies = req.headers.cookie?.split(';').map(c => c.trim());
const sessionCookie = cookies?.find(c => c.startsWith('sessionId='));
if (sessionCookie) {
sessionId = sessionCookie.split('=')[1];
if (!sessions.has(sessionId)) {
sessionId = '';
}
}
if (!sessionId) {
sessionId = generateSessionId();
res.setHeader('Set-Cookie', `sessionId=${sessionId}; HttpOnly; Path=/; Max-Age=600`);
sessions.set(sessionId, {});
}
const session = sessions.get(sessionId) || {};
// Parse URL and path
const parsedUrl = parseUrl(req.url || '');
const pathname = parsedUrl.pathname || '';
// Handle routes
if (pathname === '/auth/login') {
// Initiate OAuth flow
const state = generateSecureState();
session.oauth_state = state;
res.writeHead(302, {
'Location': `https://whitebit.com/auth/login?clientId=YOUR_CLIENT_ID&state=${state}`
});
res.end();
}
else if (pathname === '/auth/callback') {
// Handle OAuth callback
const query = parseQueryString(parsedUrl.query || '');
const receivedState = query.state as string;
const storedState = session.oauth_state;
// Clear the stored state immediately
delete session.oauth_state;
// Verify the state parameter
if (!receivedState || receivedState !== storedState) {
res.writeHead(400);
res.end('State validation failed');
return;
}
// State is valid, proceed with code exchange
const code = query.code as string;
if (code) {
// Exchange code for token
exchangeCodeForToken(code, sessionId, res);
} else {
res.writeHead(400);
res.end('Missing authorization code');
}
}
else {
// Handle other routes or 404
res.writeHead(404);
res.end('Not found');
}
});
// Exchange the authorization code for access token
function exchangeCodeForToken(
code: string,
sessionId: string,
res: http.ServerResponse
): void {
const params = new URLSearchParams({
client_id: 'YOUR_CLIENT_ID',
client_secret: 'YOUR_CLIENT_SECRET',
code: code
}).toString();
const options = {
hostname: 'whitebit.com',
port: 443,
path: '/oauth2/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(params)
}
};
const request = https.request(options, (tokenRes) => {
let data = '';
tokenRes.on('data', (chunk) => {
data += chunk;
});
tokenRes.on('end', () => {
try {
const tokenData = JSON.parse(data);
// Store tokens in session
const session = sessions.get(sessionId);
if (session) {
session.access_token = tokenData.data.access_token;
session.refresh_token = tokenData.data.refresh_token;
}
// Redirect to dashboard
res.writeHead(302, {
'Location': '/dashboard'
});
res.end();
} catch (error) {
console.error('Failed to parse token response:', error);
res.writeHead(500);
res.end('Authentication failed');
}
});
});
request.on('error', (error) => {
console.error('Token exchange failed:', error);
res.writeHead(500);
res.end('Authentication failed');
});
// Write data to request body
request.write(params);
request.end();
}
const PORT = process.env.PORT || 3000;
server.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
This approach protects users from cross-site request forgery attacks and ensures the authorization response was intended for your application.
Note: OAuth scopes are predefined during client application setup and cannot be modified during the authorization request. The access token will include all scopes that were approved during client creation.
Available Scopes
The following scopes can be requested during client setup:
Scope | Description |
---|---|
general | General API access |
show.userinfo | Access to basic user information |
users.read | Read user data |
users.email.read | Read user email information |
users.kyc.read | Information about whether a user has passed KYC verification |
orders.read | Read trading orders |
orders.create | Create trading orders |
orders.delete | Delete trading orders |
balances.read | Read account balances |
markets.read | Read market information |
deals.read | Read trading deals |
orders_history.read | Read order history |
users.transactions.read | Read user transactions |
users.converts.read | Read currency conversion history |
users.balances.read | Read user account balances |
users.orders.read | Read user orders |
users.deals.read | Read user deals |
Get Access Token
/oauth2/token
This endpoint activates an access token by exchanging an authorization code.
❗ Important Notes:
- Access token duration is 300 seconds
- The IP of the client must be added to WB Allowlist
Request Headers:
Header | Value |
---|---|
Content-Type | application/x-www-form-urlencoded |
Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
client_id | string | Yes | Your application’s client ID |
client_secret | string | Yes | Your application’s client secret |
code | string | Yes | The authorization code received from the authorization endpoint |
Response:
{
"data": {
"access_token": "MZM1MDBMMJYTNWM4MI0ZNTIYLTKXNDATNZY1MZHKM2Y2MJY3",
"expires_in": 300,
"refresh_token": "ODK5ZTVKZDUTYTI5ZC01NWJHLTGZZDMTYWFKYTNMNJHHMGZM",
"scope": "codes.apply,show.userinfo",
"token_type": "Bearer"
}
}
Error Responses:
Status 401 - Not authorized:
{
"data": {
"message": ["Invalid request"]
}
}
Status 422 - Validation errors:
{
"errors": {
"client_id": ["validation.required"],
"client_secret": ["validation.required"],
"code": ["validation.required"]
},
"notification": null
}
Refresh Token
/oauth2/refresh_token
This endpoint creates a new access token using a refresh token.
❗ Important Notes:
- Refresh token duration is 600 seconds
- Rate limit: 1 request per second
- The IP of the client must be added to WB Allowlist
Request Headers:
Header | Value |
---|---|
Content-Type | application/x-www-form-urlencoded |
Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
client_id | string | Yes | Your application’s client ID |
client_secret | string | Yes | Your application’s client secret |
token | string | Yes | The refresh token received from the token endpoint |
Response:
{
"data": {
"access_token": "NTBLZJKYNZETNJFIZC0ZNGM1LWJMYTMTODBJYZRKNWE2NMRM",
"expires_in": 300,
"refresh_token": "ODZMNMRHM2ETMZQZZI01OTQYLWEWMZATNWQ0NDYZNJBMOWUW",
"scope": "codes.apply,show.userinfo",
"token_type": "Bearer"
}
}
Error Response:
{
"data": {
"token": ["Invalid token."]
}
}
Account Endpoints
Get Account Transactions
/api/v4/accounts/transactions
This endpoint retrieves a paginated list of account transactions.
Request Headers:
Header | Value |
---|---|
Authorization | Bearer YOUR_ACCESS_TOKEN |
Content-Type | application/json |
Get Currency Conversions
/api/v4/accounts/converts
This endpoint retrieves the history of currency conversions.
Request Headers:
Header | Value |
---|---|
Authorization | Bearer YOUR_ACCESS_TOKEN |
Content-Type | application/json |
Get Orders History
/api/v4/accounts/orders
This endpoint retrieves the history of trading orders.
Request Headers:
Header | Value |
---|---|
Authorization | Bearer YOUR_ACCESS_TOKEN |
Content-Type | application/json |
Get Executed Deals
/api/v4/accounts/deals
This endpoint retrieves the history of executed deals.
Request Headers:
Header | Value |
---|---|
Authorization | Bearer YOUR_ACCESS_TOKEN |
Content-Type | application/json |
Get Main Account Balance
/api/v4/accounts/balances/main
This endpoint retrieves the main account balance information.
Request Headers:
Header | Value |
---|---|
Authorization | Bearer YOUR_ACCESS_TOKEN |
Content-Type | application/json |
Get Spot Account Balance
/api/v4/accounts/balances/spot
This endpoint retrieves the spot trading account balance information.
Request Headers:
Header | Value |
---|---|
Authorization | Bearer YOUR_ACCESS_TOKEN |
Content-Type | application/json |