OAuth Client
The Paybin OAuth Client is a fully-typed TypeScript client that wraps all Paybin OAuth API endpoints. It handles authentication, account selection, and provides a clean interface for wallets, deposits, sends, swaps, and transaction queries.
Overview
The OAuth Client provides methods for all Paybin OAuth API operations:
| Method | Endpoint | Scope(s) | TFA |
|---|---|---|---|
getSession() | GET /session | paybin:wallet paybin:merchant | - |
getWallets() | GET /wallets | paybin:wallet | - |
getWalletAddress() | GET /wallets/{symbol}/address | paybin:wallet | - |
createDepositAddress() | POST /deposit/address/create | paybin:wallet | - |
getAccounts() | GET /accounts | paybin:merchant | - |
switchAccount() | POST /accounts/switch | paybin:merchant | - |
sendPrecheck() | POST /send/precheck | transaction:write | - |
send() | POST /send | transaction:write | Required |
getSwapSymbols() | GET /swap/symbols | paybin:wallet | - |
swapPrecheck() | POST /swap/precheck | transaction:write | - |
swap() | POST /swap | transaction:write | Required |
getTransactions() | POST /transactions | transaction:read | - |
Base URL
https://pgw.paybin.io
All endpoints are prefixed with /api/OAuth.
Installation
Download the TypeScript client file and add it to your project:
Requirements
- TypeScript 4.5+ (or JavaScript ES2017+)
- Runtime: Node.js 18+ or any environment with native
fetchsupport - OAuth Token: Obtain via OpenID Connect flow
Quick Setup
- Download
paybin-oauth-client.tsusing the button above - Place it in your project (e.g.,
src/lib/paybin-oauth-client.ts) - Import and initialize the client
Installation
// Import the client
import { PaybinOAuthClient } from './paybin-oauth-client';
// Initialize with your OAuth token
const client = new PaybinOAuthClient({
baseUrl: 'https://pgw.paybin.io',
accessToken: 'your-oauth-access-token'
});
// 1. Get session to retrieve available accounts
const session = await client.getSession();
// 2. Set account GUID (required for all other endpoints)
client.setAccountGuid(session.data.accounts[0].guid);
// 3. Now you can call any endpoint
const wallets = await client.getWallets();
console.log('Total balance:', wallets.data.totalBalance);
Authentication and Headers
The Paybin OAuth API uses three types of headers for authentication and authorization:
| Header | Required For | Description |
|---|---|---|
Authorization | All endpoints | Bearer {access_token} - Your OAuth access token |
X-Account-Guid | All except /session | The active account GUID from getSession() |
TFA | /send, /swap | 6-digit two-factor authentication code |
The X-Account-Guid header is managed automatically by the client. Call setAccountGuid() once after retrieving the session, and it will be included in all subsequent requests.
Required OAuth Scopes
Your OAuth token must include the appropriate scopes for the endpoints you need to access. Request these scopes during the OIDC authorization flow.
| Scope | Endpoints | Description |
|---|---|---|
paybin:wallet | Session, Wallets, Wallet Address, Deposit Address, Swap Symbols | Access to wallet and deposit operations |
paybin:merchant | Session, Accounts, Switch Account | Access to merchant account management |
transaction:write | Send Precheck, Send, Swap Precheck, Swap | Execute send and swap transactions |
transaction:read | Transactions | Read transaction history |
The Session endpoint (/session) requires both paybin:wallet and paybin:merchant scopes. Make sure your OIDC authorization request includes all scopes needed for your integration.
Session
Get session information and the list of available accounts. This is the only endpoint that does not require the X-Account-Guid header.
GET /api/OAuth/session
Required Scopes: paybin:wallet paybin:merchant
Returns the authenticated user's information and the list of accounts they have access to. Use this as the first call after obtaining an OAuth token.
Response Fields
- Name
isAuthenticated- Type
- boolean
- Description
Whether the current OAuth token is valid and the user is authenticated.
- Name
user- Type
- object | null
- Description
User information including
userGuid,name, andemail.
- Name
accounts- Type
- AccountInfo[]
- Description
List of accounts the user has access to. Each account includes
guid,name,isPersonalAccount, androle.
- Name
currentAccountGuid- Type
- string | null
- Description
The currently active account GUID, if any.
Get Session
import { PaybinOAuthClient } from './paybin-oauth-client';
const client = new PaybinOAuthClient({
baseUrl: 'https://pgw.paybin.io',
accessToken: 'your-oauth-token'
});
const session = await client.getSession();
if (session.data.isAuthenticated) {
console.log('User:', session.data.user?.name);
console.log('Email:', session.data.user?.email);
// List available accounts
session.data.accounts.forEach(acc => {
console.log(`${acc.name} (${acc.role}) - ${acc.guid}`);
});
// Set account for subsequent requests
client.setAccountGuid(session.data.accounts[0].guid);
}
Response
{
"apiVersion": "1.0.0.0",
"data": {
"isAuthenticated": true,
"user": {
"userGuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "John Doe",
"email": "john@example.com"
},
"accounts": [
{
"guid": "11111111-2222-3333-4444-555555555555",
"name": "My Business Account",
"isPersonalAccount": false,
"role": "MerchantAdministrator"
},
{
"guid": "66666666-7777-8888-9999-000000000000",
"name": "Personal Wallet",
"isPersonalAccount": true,
"role": "Agent"
}
],
"currentAccountGuid": null
},
"code": 200,
"message": "OK"
}
Exception
{
"apiVersion": "1.0.0.0",
"data": false,
"code": 401,
"message": "Unauthorized"
}
Wallets
Retrieve wallet balances and deposit addresses for the active account.
Get Wallets
GET /api/OAuth/wallets
Required Scope: paybin:wallet
Returns all wallet balances with total balance and daily profit for the active account.
Response Fields
- Name
totalBalance- Type
- number
- Description
Total balance across all wallets in USD.
- Name
dailyProfit- Type
- number
- Description
Daily profit/loss in USD.
- Name
wallets- Type
- WalletInfo[]
- Description
Array of wallet objects with
symbol,name,displayName,network,price,amount,balanceFiatAmount, andaddress.
Get Wallets
const wallets = await client.getWallets();
console.log('Total Balance:', wallets.data.totalBalance, 'USD');
console.log('Daily P/L:', wallets.data.dailyProfit, 'USD');
wallets.data.wallets.forEach(w => {
console.log(`${w.displayName}: ${w.amount} ${w.symbol}`);
console.log(` Value: $${w.balanceFiatAmount}`);
console.log(` Price: $${w.price}`);
});
Response
{
"apiVersion": "1.0.0.0",
"data": {
"totalBalance": 12450.75,
"dailyProfit": 125.30,
"wallets": [
{
"symbolId": 1,
"symbol": "BTC",
"name": "Bitcoin",
"displayName": "Bitcoin (BTC)",
"network": "Bitcoin Mainnet",
"price": 67500.00,
"amount": 0.15,
"balanceFiatAmount": 10125.00,
"address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
},
{
"symbolId": 2,
"symbol": "ETH",
"name": "Ethereum",
"displayName": "Ethereum (ETH)",
"network": "Ethereum Mainnet",
"price": 3500.00,
"amount": 0.665,
"balanceFiatAmount": 2327.50,
"address": "0x742d35Cc6634C0532925a3b844C9db96C4b4d8b6"
}
]
},
"code": 200,
"message": "OK"
}
Get Wallet Address
GET /api/OAuth/wallets/{symbol}/address
Required Scope: paybin:wallet
Returns the deposit address for a specific cryptocurrency symbol.
- Name
symbol- Type
- string
- Description
Path parameter. The cryptocurrency symbol (e.g.,
BTC,ETH,USDT).
Response Fields
- Name
symbolName- Type
- string
- Description
Full name of the cryptocurrency.
- Name
symbol- Type
- string
- Description
Cryptocurrency symbol.
- Name
displayName- Type
- string
- Description
User-friendly display name.
- Name
network- Type
- string
- Description
Blockchain network name.
- Name
address- Type
- string
- Description
The deposit wallet address.
Get Wallet Address
const btcAddress = await client.getWalletAddress('BTC');
console.log('Symbol:', btcAddress.data.symbol);
console.log('Network:', btcAddress.data.network);
console.log('Address:', btcAddress.data.address);
Response
{
"apiVersion": "1.0.0.0",
"data": {
"symbolName": "Bitcoin",
"symbol": "BTC",
"displayName": "Bitcoin (BTC)",
"network": "Bitcoin Mainnet",
"address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
},
"code": 200,
"message": "OK"
}
Deposit Address
Create new deposit addresses with callback support for tracking payments.
POST /api/OAuth/deposit/address/create
Required Scope: paybin:wallet
Generates a new deposit address for a specific cryptocurrency. Supports webhook callbacks for deposit notifications.
- Name
symbol- Type
- string
- Description
Cryptocurrency symbol (e.g.,
See all SymbolsETH,BTC,USDT).
- Name
label- Type
- string
- Description
A user-friendly label for the deposit address, helping you identify the purpose of the deposit.
- Name
referenceId- Type
- string
- Description
A unique identifier for the deposit request, used for tracking and reconciliation.
- Name
callbackUrl- Type
- string
- Description
URL where Paybin will send webhook notifications when deposits are received.
- Name
amount- Type
- number
- Description
Optional. Expected deposit amount for price calculation.
- Name
currency- Type
- string
- Description
Optional. Fiat currency code for price calculation (USD, EUR, etc.).
Create Deposit Address
const deposit = await client.createDepositAddress({
symbol: 'ETH',
label: 'Customer Payment #1234',
referenceId: 'ORDER-1234',
callbackUrl: 'https://myapp.com/webhooks/paybin',
amount: 100,
currency: 'USD'
});
console.log('Deposit to:', deposit.data.wallet);
console.log('Network:', deposit.data.network);
console.log('Request ID:', deposit.data.requestId);
Response
{
"apiVersion": "1.0.0.0",
"data": {
"wallet": "0x742d35Cc6634C0532925a3b844C9db96C4b4d8b6",
"symbol": "ETH",
"network": "Ethereum Mainnet",
"referenceId": "ORDER-1234",
"requestId": "550e8400-e29b-41d4-a716-446655440000"
},
"code": 200,
"message": "OK"
}
Exception
{
"apiVersion": "1.0.0.0",
"data": false,
"code": 400,
"message": "Invalid symbol"
}
Accounts
Manage account profiles and switch between connected accounts.
Get Account Profile
GET /api/OAuth/accounts
Required Scope: paybin:merchant
Returns the profile information for the active account.
Response Fields
- Name
name- Type
- string
- Description
Account holder name.
- Name
email- Type
- string
- Description
Account email address.
- Name
merchantGuid- Type
- string
- Description
Merchant unique identifier.
- Name
role- Type
- string
- Description
User role in this account (
MerchantAdministrator,Agent, etc.).
- Name
connectedAccounts- Type
- AccountInfo[]
- Description
List of other accounts the user has access to.
- Name
companyCount- Type
- number
- Description
Number of companies associated with the account.
- Name
userGuid- Type
- string
- Description
User unique identifier.
Get Account Profile
const profile = await client.getAccounts();
console.log('Name:', profile.data.name);
console.log('Email:', profile.data.email);
console.log('Role:', profile.data.role);
console.log('Merchant GUID:', profile.data.merchantGuid);
profile.data.connectedAccounts.forEach(acc => {
console.log(`Connected: ${acc.name} (${acc.role})`);
});
Response
{
"apiVersion": "1.0.0.0",
"data": {
"companyCount": 2,
"name": "John Doe",
"email": "john@example.com",
"merchantGuid": "m-11111111-2222-3333-4444-555555555555",
"role": "MerchantAdministrator",
"connectedAccounts": [
{
"guid": "66666666-7777-8888-9999-000000000000",
"name": "Secondary Business",
"isPersonalAccount": false,
"role": "Agent"
}
],
"userGuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
},
"code": 200,
"message": "OK"
}
Switch Account
POST /api/OAuth/accounts/switch
Required Scope: paybin:merchant
Switch to a different account and receive the new account's wallet information.
- Name
accountGuid- Type
- string
- Description
The GUID of the account to switch to. Must be one of the accounts from
getSession()orgetAccounts().
After switching accounts, remember to call client.setAccountGuid() with the new account GUID to update the client's headers.
Switch Account
const result = await client.switchAccount(
'66666666-7777-8888-9999-000000000000'
);
console.log('Switched to:', result.data.currentAccountGuid);
console.log('Total balance:', result.data.totalBalance);
// Update client's account GUID
client.setAccountGuid(result.data.currentAccountGuid);
Response
{
"apiVersion": "1.0.0.0",
"data": {
"currentAccountGuid": "66666666-7777-8888-9999-000000000000",
"accounts": [
{
"guid": "11111111-2222-3333-4444-555555555555",
"name": "My Business Account",
"isPersonalAccount": false,
"role": "MerchantAdministrator"
},
{
"guid": "66666666-7777-8888-9999-000000000000",
"name": "Secondary Business",
"isPersonalAccount": false,
"role": "Agent"
}
],
"totalBalance": 5230.50,
"dailyProfit": -12.40,
"wallets": [
{
"symbolId": 1,
"symbol": "BTC",
"name": "Bitcoin",
"displayName": "Bitcoin (BTC)",
"network": "Bitcoin Mainnet",
"price": 67500.00,
"amount": 0.05,
"balanceFiatAmount": 3375.00,
"address": "bc1q..."
}
]
},
"code": 200,
"message": "OK"
}
Send
Send cryptocurrency to external addresses. Requires MerchantAdministrator or Agent role.
Send Precheck
POST /api/OAuth/send/precheck
Required Scope: transaction:write
Validate a send transaction and retrieve available fee options before executing. Always call this before send() to show the user fee estimates.
- Name
symbol- Type
- string
- Description
Cryptocurrency symbol to send (e.g.,
BTC,ETH).
- Name
address- Type
- string
- Description
Destination wallet address.
- Name
amount- Type
- number
- Description
Amount to send in crypto units.
Response Fields
- Name
feeData- Type
- FeeData[]
- Description
Array of fee options. Each contains
feeRate(0=Low, 1=Standard, 2=High),fee,arrivalEstimation,symbol, andusdequivalent.
- Name
price- Type
- number
- Description
Current price of the cryptocurrency in USD.
- Name
availableBalance- Type
- number
- Description
Available balance for sending.
Send Precheck
const precheck = await client.sendPrecheck({
symbol: 'BTC',
address: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
amount: 0.01
});
console.log('Available:', precheck.data.availableBalance, 'BTC');
console.log('Price:', precheck.data.price, 'USD');
precheck.data.feeData.forEach(fee => {
const rate = ['Low', 'Standard', 'High'][fee.feeRate];
console.log(`${rate}: ${fee.fee} ${fee.symbol} (~$${fee.usd})`);
console.log(` ETA: ${fee.arrivalEstimation}`);
});
Response
{
"apiVersion": "1.0.0.0",
"data": {
"feeData": [
{
"feeRate": 0,
"fee": 0.00005,
"arrivalEstimation": "~60 minutes",
"symbol": "BTC",
"usd": 3.38
},
{
"feeRate": 1,
"fee": 0.0001,
"arrivalEstimation": "~30 minutes",
"symbol": "BTC",
"usd": 6.75
},
{
"feeRate": 2,
"fee": 0.0002,
"arrivalEstimation": "~10 minutes",
"symbol": "BTC",
"usd": 13.50
}
],
"price": 67500.00,
"availableBalance": 0.15,
"symbol": "BTC",
"address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"amount": 0.01
},
"code": 200,
"message": "OK"
}
Execute Send
POST /api/OAuth/send
Required Scope: transaction:write | TFA: Required
Execute a cryptocurrency send transaction. Requires the TFA header with a 6-digit two-factor authentication code.
- Name
symbol- Type
- string
- Description
Cryptocurrency symbol to send.
- Name
address- Type
- string
- Description
Destination wallet address.
- Name
amount- Type
- number
- Description
Amount to send in crypto units.
- Name
feeRate- Type
- FeeRate
- Description
Fee rate selection:
0(Low),1(Standard),2(High).
- Name
referenceId- Type
- string
- Description
Optional. Your internal reference ID for tracking.
- Name
description- Type
- string
- Description
Optional. Description for the transaction.
The send() method requires a 6-digit TFA code as the second parameter. The client automatically sets the TFA header.
Execute Send
import { FeeRate } from './paybin-oauth-client';
const result = await client.send({
symbol: 'BTC',
address: 'bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh',
amount: 0.01,
feeRate: FeeRate.Standard,
referenceId: 'PAYMENT-001',
description: 'Invoice payment'
}, '123456'); // TFA code
console.log('TX ID:', result.data.txId);
console.log('Explorer:', result.data.explorerUrl);
Response
{
"apiVersion": "1.0.0.0",
"data": {
"txId": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",
"explorerUrl": "https://blockchair.com/bitcoin/transaction/a1b2c3d4..."
},
"code": 200,
"message": "OK"
}
Exception
{
"apiVersion": "1.0.0.0",
"data": false,
"code": 403,
"message": "Insufficient permissions for send operation"
}
Swap
Swap between cryptocurrencies. Requires MerchantAdministrator or Agent role.
Get Swap Symbols
GET /api/OAuth/swap/symbols
Required Scope: paybin:wallet
Returns available swap pairs and current balances.
Response Fields
- Name
symbolList- Type
- SwapSymbolInfo[]
- Description
Available swap symbols. Each contains
baseSymbol,quoteSymbols(available targets),depositNetworks, andwithdrawNetworks.
- Name
balance- Type
- SwapBalance
- Description
Current balances for swap-eligible currencies:
btcBalance,ethBalance,usdtBalance,trxBalance,bnbBalance,ltcBalance,solBalance,avaxBalance.
Get Swap Symbols
const symbols = await client.getSwapSymbols();
symbols.data.symbolList.forEach(s => {
console.log(`${s.baseSymbol} -> ${s.quoteSymbols.join(', ')}`);
console.log(` Deposit networks: ${s.depositNetworks.join(', ')}`);
console.log(` Withdraw networks: ${s.withdrawNetworks.join(', ')}`);
});
console.log('BTC Balance:', symbols.data.balance.btcBalance);
console.log('ETH Balance:', symbols.data.balance.ethBalance);
Response
{
"apiVersion": "1.0.0.0",
"data": {
"symbolList": [
{
"baseSymbol": "BTC",
"quoteSymbols": ["ETH", "USDT", "BNB", "LTC"],
"depositNetworks": ["Bitcoin"],
"withdrawNetworks": ["Bitcoin"]
},
{
"baseSymbol": "ETH",
"quoteSymbols": ["BTC", "USDT", "BNB"],
"depositNetworks": ["Ethereum", "Optimism"],
"withdrawNetworks": ["Ethereum", "Optimism"]
}
],
"balance": {
"btcBalance": 0.15,
"ethBalance": 2.5,
"usdtBalance": 1500.00,
"trxBalance": 500.00,
"bnbBalance": 1.2,
"ltcBalance": 10.0,
"solBalance": 25.0,
"avaxBalance": 15.0
}
},
"code": 200,
"message": "OK"
}
Swap Precheck
POST /api/OAuth/swap/precheck
Required Scope: transaction:write
Calculate swap amounts before executing. Use this to show the user how much they will receive.
- Name
fromSymbol- Type
- string
- Description
Source cryptocurrency symbol.
- Name
fromNetwork- Type
- string
- Description
Source network name (e.g.,
Bitcoin,Ethereum).
- Name
toSymbol- Type
- string
- Description
Target cryptocurrency symbol.
- Name
toNetwork- Type
- string
- Description
Target network name.
- Name
amount- Type
- number
- Description
Amount to swap.
- Name
isUsdInput- Type
- boolean
- Description
If
true, theamountis interpreted as USD value. Iffalse, it is in crypto units.
Swap Precheck
const precheck = await client.swapPrecheck({
fromSymbol: 'BTC',
fromNetwork: 'Bitcoin',
toSymbol: 'ETH',
toNetwork: 'Ethereum',
amount: 0.01,
isUsdInput: false
});
console.log('Will send:', precheck.data.cryptoAmount, 'BTC');
console.log('Will receive:', precheck.data.toAmount, 'ETH');
Response
{
"apiVersion": "1.0.0.0",
"data": {
"cryptoAmount": 0.01,
"toAmount": 1.928
},
"code": 200,
"message": "OK"
}
Execute Swap
POST /api/OAuth/swap
Required Scope: transaction:write | TFA: Required
Execute a swap transaction. Requires the TFA header with a 6-digit code.
- Name
fromSymbol- Type
- string
- Description
Source cryptocurrency symbol.
- Name
fromNetwork- Type
- string
- Description
Source network name.
- Name
toSymbol- Type
- string
- Description
Target cryptocurrency symbol.
- Name
toNetwork- Type
- string
- Description
Target network name.
- Name
amount- Type
- number
- Description
Amount to swap.
- Name
isUsdInput- Type
- boolean
- Description
Whether the amount is in USD.
Execute Swap
const result = await client.swap({
fromSymbol: 'BTC',
fromNetwork: 'Bitcoin',
toSymbol: 'ETH',
toNetwork: 'Ethereum',
amount: 0.01,
isUsdInput: false
}, '123456'); // TFA code
console.log('Swap Reference:', result.data.swapReferenceId);
console.log('Status:', result.data.statusCode);
if (result.data.sendResult) {
console.log('TX ID:', result.data.sendResult.txId);
console.log('Explorer:', result.data.sendResult.explorerUrl);
}
Response
{
"apiVersion": "1.0.0.0",
"data": {
"address": "0x742d35Cc6634C0532925a3b844C9db96C4b4d8b6",
"swapReferenceId": "SWAP-550e8400-e29b-41d4-a716-446655440000",
"sendResult": {
"txId": "a1b2c3d4e5f6...",
"explorerUrl": "https://blockchair.com/bitcoin/transaction/a1b2c3d4..."
},
"errorCode": null,
"statusCode": 200
},
"code": 200,
"message": "OK"
}
Exception
{
"apiVersion": "1.0.0.0",
"data": false,
"code": 403,
"message": "Insufficient permissions for swap operation"
}
Transactions
Query paginated transaction history for deposits and withdrawals.
POST /api/OAuth/transactions
Required Scope: transaction:read
Returns a paginated list of transactions with filtering and sorting support.
Request Parameters
- Name
page- Type
- number
- Description
Page number (starting from 1).
- Name
recordsPerPage- Type
- number
- Description
Number of records per page.
- Name
filter- Type
- string
- Description
Optional. Text filter for searching transactions.
- Name
orderBy- Type
- string
- Description
Optional. Field name to order results by.
- Name
sortOrder- Type
- 'asc' | 'desc'
- Description
Optional. Sort direction.
- Name
symbols- Type
- string[]
- Description
Optional. Filter by cryptocurrency symbols (e.g.,
["BTC", "ETH"]).
- Name
withdrawTypes- Type
- number[]
- Description
Optional. Filter by withdrawal types.
- Name
hideLowAmounts- Type
- boolean
- Description
Optional. Hide transactions with very small amounts.
Response Fields
- Name
totalRecords- Type
- number
- Description
Total number of matching transactions.
- Name
totalPages- Type
- number
- Description
Total number of pages.
- Name
items- Type
- TransactionItem[]
- Description
Transaction list. Each item includes
symbol,amount,status,type(Deposit/Withdraw),date,txId,address,referenceId,prices, and more.
Get Transactions
const transactions = await client.getTransactions({
page: 1,
recordsPerPage: 20,
symbols: ['BTC', 'ETH'],
sortOrder: 'desc',
hideLowAmounts: true
});
console.log('Total:', transactions.data.totalRecords);
console.log('Pages:', transactions.data.totalPages);
transactions.data.items.forEach(tx => {
console.log(`${tx.date} | ${tx.type} | ${tx.amount} ${tx.symbol}`);
console.log(` Status: ${tx.status}`);
console.log(` Value: $${tx.prices.usd}`);
if (tx.txId) {
console.log(` TX: ${tx.txId}`);
}
});
Response
{
"apiVersion": "1.0.0.0",
"data": {
"totalRecords": 142,
"totalPages": 8,
"page": 1,
"recordsPerPage": 20,
"items": [
{
"symbolId": 1,
"symbol": "BTC",
"symbolName": "Bitcoin",
"displayName": "Bitcoin (BTC)",
"address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"txId": "a1b2c3d4e5f6...",
"amount": 0.05,
"status": "Completed",
"type": "Deposit",
"date": "2026-03-10T14:30:00Z",
"value": 3375.00,
"referenceId": "ORDER-5678",
"label": "Customer deposit",
"merchantTransactionId": "mt-12345",
"to": "",
"withdrawType": 0,
"prices": {
"usd": 3375.00,
"eur": 3100.00,
"gbp": 2650.00,
"try": 108000.00,
"jpy": 505000.00
},
"isAutoCollected": false
}
]
},
"code": 200,
"message": "OK"
}
Error Handling
The client throws PaybinApiError for all API errors with structured error information.
import { PaybinOAuthClient, PaybinApiError } from './paybin-oauth-client';
try {
const wallets = await client.getWallets();
} catch (error) {
if (error instanceof PaybinApiError) {
console.error('API Error:', error.message);
console.error('Error Code:', error.code);
switch (error.code) {
case 401:
// Token expired - refresh and retry
console.error('Token expired. Please re-authenticate.');
break;
case 403:
// Insufficient permissions
console.error('Access denied. Check your role and permissions.');
break;
case 400:
// Bad request
console.error('Invalid request parameters.');
break;
default:
console.error('Unexpected error:', error.response);
}
} else if (error instanceof Error) {
// Client-side errors (e.g., missing account GUID)
console.error('Client Error:', error.message);
}
}
Common Error Codes
| Code | Message | Description |
|---|---|---|
| 401 | Unauthorized | Invalid or expired OAuth token |
| 403 | Access denied to this account | User doesn't have permission for the requested account |
| 403 | Insufficient permissions for send operation | User role doesn't allow send (requires Admin or Agent) |
| 400 | X-Account-Guid header is required | Missing account GUID header (call setAccountGuid()) |
| 400 | Invalid symbol | Unsupported cryptocurrency symbol |
| 400 | Insufficient balance | Not enough funds for the operation |
| 429 | Rate limit exceeded | Too many requests, implement backoff |
Best Practices
๐ Security
- Store OAuth tokens securely and never expose them in client-side code
- Always use HTTPS for API communications
- Implement token refresh logic before tokens expire
- Never log access tokens or TFA codes
- Validate all API responses before processing
๐ Integration Flow
- Always call
getSession()first to get available accounts - Set
accountGuidbefore calling any other endpoint - Use
sendPrecheck()/swapPrecheck()before executing transactions - Implement proper error handling for all API calls
- Use unique
referenceIdvalues for deposit addresses and send operations
๐ Monitoring
- Track transaction statuses for deposit and withdrawal operations
- Implement webhook handlers for deposit callbacks
- Monitor wallet balances for reconciliation
- Log all API errors for debugging
๐จ Error Handling
- Handle
PaybinApiErrorseparately from network errors - Implement retry logic with exponential backoff for transient failures
- Check for specific error codes to provide actionable feedback to users
- Handle TFA errors gracefully with user-friendly prompts
๐ฐ Transaction Safety
- Always call precheck endpoints before send or swap operations
- Display fee information to users before confirming transactions
- Validate amounts against available balances client-side
- Store
txIdandreferenceIdfor all transactions for audit trails