@arminbcbtest/sdk
v0.1.1
Published
The official BCB TypeScript SDK with comprehensive acceptance testing
Maintainers
Readme
BCB Connect - TypeScript SDK
The official TypeScript/JavaScript SDK for BCB Group APIs, designed with the same developer experience principles as Stripe's SDK. This project includes a comprehensive acceptance testing infrastructure that runs against real external servers.
🚀 Quick Start
Installation
npm install @bcb/sdkBasic Usage
import BCB from '@bcb/sdk';
const bcb = new BCB({
clientId: 'your_client_id',
clientSecret: 'your_client_secret',
environment: 'sandbox', // 'sandbox' or 'production'
});
// The SDK handles authentication automatically
// List all accounts
const accounts = await bcb.accounts.list();
console.log(`Found ${accounts.data.length} accounts`);
// Get a specific account
if (accounts.data.length > 0) {
const account = await bcb.accounts.retrieve(accounts.data[0].id);
console.log(`Account: ${account.data.account_label}`);
// Get account balance
const balance = await bcb.balances.get(account.data.id);
console.log(`Balance: ${balance.data.length} entries`);
// Get recent transactions
const transactions = await bcb.transactions.list(account.data.id, { limit: 10 });
console.log(`Recent transactions: ${transactions.data.length}`);
// Make a payment
const payment = await bcb.payments.createGBPFPS({
counterparty_id: account.data.counterparty_id,
sender_account_id: account.data.id,
beneficiary_name: 'John Smith',
beneficiary_account_number: '12345678',
beneficiary_sort_code: '200000',
amount: '100.50',
reference: 'Invoice payment',
reason: 'GDSV' // Purchase/Sale of Goods and Services
});
console.log(`Payment created: ${payment.data[0].transactionId}`);
}🧪 Comprehensive Testing Infrastructure
This SDK includes a robust acceptance testing framework designed to validate functionality against real BCB API servers. The testing infrastructure is built with three distinct layers:
Test Architecture
- Unit Tests (
tests/unit/) - Fast, isolated component testing - Integration Tests (
tests/integration/) - Real API integration testing - Acceptance Tests (
tests/acceptance/) - End-to-end scenarios and performance testing
Key Testing Features
✅ Real API Testing - Tests run against actual BCB servers, not mocks
✅ Multi-Environment Support - Development, staging, production configurations
✅ Performance Monitoring - Built-in performance tracking and assertions
✅ Custom Jest Matchers - BCB-specific test assertions
✅ Comprehensive Error Testing - Real error scenario validation
✅ Load Testing - Concurrent request and performance testing
✅ Event System Testing - SDK event emission validation
Running Tests
# Check test environment configuration
npm run test:env:check
# Run all tests
npm test
# Run specific test types
npm run test:unit # Unit tests only
npm run test:integration # Integration tests with real API
npm run test:acceptance # Full acceptance test suite
# Development testing
npm run test:watch # Watch mode
npm run test:coverage # Coverage reportTest Configuration
Copy environment template:
cp env.example .envConfigure for your environment:
# Required: BCB API credentials BCB_CLIENT_ID=your_client_id BCB_CLIENT_SECRET=your_client_secret # Environment configuration (sandbox or production) BCB_ENVIRONMENT=sandbox # sandbox|production # Optional: Override specific URLs (if not using predefined environments) # BCB_BASE_URL=https://api.bcb.group # BCB_AUTH_URL=https://auth.bcb.group # BCB_CLIENT_API_URL=https://client-api.bcb.group # Optional configuration BCB_TIMEOUT=30000 # Request timeout in ms BCB_MAX_RETRIES=3 # Max retry attemptsVerify configuration:
npm run test:env:check
📖 SDK Documentation
Environment Configuration
The BCB SDK supports multiple environments with predefined URL configurations:
Predefined Environments
import BCB from '@bcb/sdk';
// Sandbox environment (recommended for development and testing)
const sandboxBcb = new BCB({
clientId: 'your_client_id',
clientSecret: 'your_client_secret',
environment: 'sandbox', // Uses *.uat.bcb.group URLs
});
// Production environment
const prodBcb = new BCB({
clientId: 'your_client_id',
clientSecret: 'your_client_secret',
environment: 'production', // Uses *.bcb.group URLs (default)
});Environment URLs
| Environment | Auth URL | Base API URL | Client API URL |
|-------------|----------|--------------|----------------|
| sandbox | https://auth.uat.bcb.group | https://api.uat.bcb.group | https://client-api.uat.bcb.group |
| production | https://auth.bcb.group | https://api.bcb.group | https://client-api.bcb.group |
Custom URLs
You can also override specific URLs when needed:
const bcb = new BCB({
clientId: 'your_client_id',
clientSecret: 'your_client_secret',
// Custom URLs override environment settings
baseURL: 'https://custom-api.example.com',
authURL: 'https://custom-auth.example.com',
clientApiURL: 'https://custom-client-api.example.com',
});Multiple API Endpoints
The SDK provides methods to interact with different API endpoints:
// Base API requests (most common)
const response = await bcb.request('/endpoint');
// Auth API requests (handled automatically, but available if needed)
const authResponse = await bcb.authRequest('/oauth/token');
// Client API requests
const clientResponse = await bcb.clientRequest('/client-endpoint');Configuration
import { BCB } from '@bcb/sdk';
const bcb = new BCB({
clientId: 'your_client_id',
clientSecret: 'your_client_secret',
baseURL: 'https://api.bcb.group', // optional
timeout: 30000, // optional
maxRetries: 3, // optional
});Authentication
The SDK handles OAuth2 client credentials flow automatically:
// Authentication happens automatically on first API call
const response = await bcb.get('/protected-endpoint');
// Manual token management
const token = await bcb.auth.getAccessToken();
const isAuth = bcb.auth.isAuthenticated();
await bcb.auth.refreshToken();Accounts Management
The SDK provides comprehensive account listing functionality with Stripe-like patterns:
// List all accounts
const accounts = await bcb.accounts.list();
console.log(`Found ${accounts.data.length} accounts`);
// List accounts with pagination
const paginatedAccounts = await bcb.accounts.list({
limit: 10,
pageToken: 123
});
// Filter by counterparty
const counterpartyAccounts = await bcb.accounts.listByCounterparty(483);
// Retrieve specific account by ID
const account = await bcb.accounts.retrieve(378);
console.log(`Account: ${account.data.account_label}`);
// Filter by currency (client-side filtering)
const btcAccounts = await bcb.accounts.listByCurrency('BTC');
// Filter by account type (client-side filtering)
const wallets = await bcb.accounts.listByType('Wallet');
const banks = await bcb.accounts.listByType('Bank');
const custodial = await bcb.accounts.listByType('Custodial');
// Advanced filtering with multiple parameters
const filteredAccounts = await bcb.accounts.listByCounterparty(483, {
limit: 5
});Balance Management
The SDK provides comprehensive balance functionality following the same Stripe-like patterns:
// Get current balance for an account (using numeric account ID)
const balance = await bcb.balances.get(539);
console.log(`Found ${balance.data.length} balance entries`);
// Get balance using account ID from accounts list
const accounts = await bcb.accounts.list();
const accountId = accounts.data[0].id; // Use the numeric ID
const balance = await bcb.balances.get(accountId);
// Get end-of-day balance for a specific date
const eodBalance = await bcb.balances.getEndOfDay(539, '2023-12-31');
// Using dateTo parameter directly
const dateBalance = await bcb.balances.get(539, { dateTo: '2023-12-31' });
// Retrieve method (alias for get)
const balance = await bcb.balances.retrieve(539);
// Get balances for multiple accounts
const balances = await bcb.balances.getMultiple([539, 540]);
// Filter balance by currency (client-side filtering)
const btcBalance = await bcb.balances.getByCurrency(539, 'BTC');
// Filter balance by account type (client-side filtering)
const walletBalance = await bcb.balances.getByType(539, 'Wallet');
const bankBalance = await bcb.balances.getByType(539, 'Bank');
const custodialBalance = await bcb.balances.getByType(539, 'Custodial');Balance Object Structure
interface Balance {
counterparty_id: number;
counterparty_name: string;
counterparty_country: string;
account_id: number;
cid: string; // Alpha-numeric counterparty id
pid: string; // Alpha-numeric white-label partner id
partner_id: number; // Internal numeric white-label partner id
account_label: string;
partner_name: string; // White-label partner name
account_name: string; // Account holder name
node_address: string;
node_location: string | null;
ticker: string; // Asset identifier (e.g. 'BTC', 'USD')
balance: number; // Latest balance
email: string; // Account holder email address
aid: string; // Alpha-numeric account id
account_type: 'Bank' | 'Custodial' | 'Wallet'; // Account type
payment_type: string | null;
description: string; // Free-text description of account
bcb_controlled: number; // Flag is 1 if BCB can operate the account, 0 otherwise
is_observable: number;
host_name: string;
reporting_ccy: string; // Home currency of client
iban: string;
bic: string;
host_location: string;
host_hub: string;
host_country: string;
host_country_name: string;
asset_name: string; // Common name for the asset identified by the ticker
display_name: string; // More descriptive name of the asset
image_url_trans: string; // Image URL of asset for display purposes
decimals_price: number; // Number of decimals to display in the price
decimals_quantity: number; // Number of decimals to display in the quantity
}Account Object Structure
interface Account {
id: number;
counterparty_id: number;
aid: string; // Account identifier
cid: string; // Customer identifier
account_type: 'Wallet' | 'Bank' | 'Custodial';
ccy: string; // Currency code
host_name: string; // Host institution name
host_hub: string; // Host hub location
host_location: string; // Host physical location
node_name: string; // Node name
node_address: string; // Node address
node_location: string; // Node location
node_country: string; // Node country code
node_subaddress: string; // Node subaddress
iban: string; // IBAN (for bank accounts)
account_label: string; // Human-readable label
description: string; // Account description
bcb_controlled: number; // BCB controlled flag (0/1)
settlement_reference: string;
created_at: string; // ISO timestamp
updated_at: string; // ISO timestamp
partner_id: number;
email: string; // Contact email
reporting_ccy: string; // Reporting currency
pid: string; // Partner identifier
partner_name: string; // Partner name
}Transaction Management
The SDK provides comprehensive transaction functionality for retrieving transaction history with advanced filtering options:
// List all transactions for an account (using numeric account ID)
const transactions = await bcb.transactions.list(539);
console.log(`Found ${transactions.data.length} transactions`);
// List transactions using account ID from accounts list
const accounts = await bcb.accounts.list();
const accountId = accounts.data[0].id; // Use the numeric ID
const transactions = await bcb.transactions.list(accountId);
// List transactions with pagination
const paginatedTransactions = await bcb.transactions.list(539, {
limit: 10,
pageToken: 123
});
// Filter by date range
const dateRangeTransactions = await bcb.transactions.listByDateRange(
539,
'2023-01-01',
'2023-12-31'
);
// Using date parameters directly
const filteredTransactions = await bcb.transactions.list(539, {
dateFrom: '2023-01-01',
dateTo: '2023-12-31',
limit: 50
});
// Filter by transaction type (client-side filtering)
const creditTransactions = await bcb.transactions.listCredits(539);
const debitTransactions = await bcb.transactions.listDebits(539);
// Get transactions for multiple accounts
const multipleTransactions = await bcb.transactions.listMultiple([539, 540]);
// Alias method for consistency
const transactions = await bcb.transactions.listForAccount(539);
// Advanced filtering with multiple parameters
const advancedTransactions = await bcb.transactions.list(539, {
dateFrom: '2023-01-01',
dateTo: '2023-12-31',
limit: 20
});
// Get specific transaction detail by ID
const transactionDetail = await bcb.transactions.retrieveDetail(539, '7b73263d-65dc-11e9-b39c-42010a8400a9');
console.log(`Transaction: ${transactionDetail.data.tx_id}`);
console.log(`Amount: ${transactionDetail.data.amount} ${transactionDetail.data.ticker}`);
console.log(`Network: ${transactionDetail.data.network}`);
console.log(`Type: ${transactionDetail.data.credit ? 'Credit' : 'Debit'}`);
console.log(`Status: ${transactionDetail.data.approved ? 'Approved' : 'Pending'}`);
// Access detailed bank information
if (transactionDetail.data.details.iban) {
console.log(`IBAN: ${transactionDetail.data.details.iban}`);
console.log(`Account Name: ${transactionDetail.data.details.account_name}`);
console.log(`Reference: ${transactionDetail.data.details.reference}`);
}
// Retrieve alias method (same as retrieveDetail)
const transaction = await bcb.transactions.retrieve(539, '7b73263d-65dc-11e9-b39c-42010a8400a9');Transaction Object Structure
interface Transaction {
tx_id: string; // Unique transaction ID
account_id: number; // Internal numeric account ID
blinc_id?: string | null; // BLINC network ID (if applicable)
network?: string; // Payment network (e.g., 'FPS', 'Bitcoin')
value_date: string; // Transaction date (ISO timestamp)
credit: number; // 1 for credit, 0 for debit
details: TransactionDetails; // Transaction details object
ticker: string; // Asset identifier (e.g., 'BTC', 'GBP', 'USD')
amount: number; // Transaction amount
approved: number; // 1 for approved, 0 for pending
notes?: string | null; // Optional transaction notes
source_name?: string; // Source system name (e.g., 'clearbank')
}
interface TransactionDetails {
bic?: string | null; // Bank Identifier Code
iban?: string | null; // International Bank Account Number
blinc_id?: string | null; // BLINC network identifier
reference?: string; // Payment reference
sort_code?: string; // Bank sort code
account_name?: string; // Account holder name
account_number?: string; // Account number
counterparty_reference?: string; // Counterparty reference
endToEndIdentifier?: string; // End-to-end identifier
nonce?: number; // Unique nonce value
}HTTP Methods
// GET request
const users = await bcb.get('/users');
// POST request
const newUser = await bcb.post('/users', {
name: 'John Doe',
email: '[email protected]',
});
// PUT, PATCH, DELETE
const updated = await bcb.put('/users/123', userData);
const patched = await bcb.patch('/users/123', { name: 'Jane' });
await bcb.delete('/users/123');Error Handling
import {
BCBAuthenticationError,
BCBRateLimitError,
BCBAPIError
} from '@bcb/sdk';
try {
const response = await bcb.get('/endpoint');
} catch (error) {
if (error instanceof BCBAuthenticationError) {
console.error('Auth failed:', error.message);
} else if (error instanceof BCBRateLimitError) {
console.error('Rate limited:', error.headers?.['retry-after']);
}
}Beneficiaries Management
The SDK provides comprehensive beneficiary management functionality following the same Stripe-like patterns:
// List all beneficiaries
const beneficiaries = await bcb.beneficiaries.list();
console.log(`Found ${beneficiaries.data.length} beneficiaries`);
// List beneficiaries with pagination
const paginatedBeneficiaries = await bcb.beneficiaries.list({
limit: 10,
pageToken: 123
});
// Retrieve specific beneficiary by ID
const beneficiary = await bcb.beneficiaries.retrieve(378);
console.log(`Beneficiary: ${beneficiary.data.account_label}`);
// Filter by currency (client-side filtering)
const btcBeneficiaries = await bcb.beneficiaries.listByCurrency('BTC');
// Filter by account type (client-side filtering)
const wallets = await bcb.beneficiaries.listByType('Wallet');
const banks = await bcb.beneficiaries.listByType('Bank');
const custodial = await bcb.beneficiaries.listByType('Custodial');
// Filter by counterparty (client-side filtering)
const counterpartyBeneficiaries = await bcb.beneficiaries.listByCounterparty(483);
// Advanced filtering with multiple parameters
const filteredBeneficiaries = await bcb.beneficiaries.listByCurrency('BTC', {
limit: 5
});Beneficiary Object Structure
interface Beneficiary {
id: number; // Numeric internal beneficiary ID
counterparty_id: number; // Numeric internal counterparty ID
aid: string; // Alpha-numeric beneficiary ID
cid: string; // Alpha-numeric counterparty ID
account_type: 'Wallet' | 'Bank' | 'Custodial'; // Account type
ccy: string; // Asset ticker, or left hand side of trading symbol
host_name: string; // Bank Name for bank accounts, Custodian Name for custody accounts, Wallet Name for wallet accounts
host_hub: string; // Branch Code for bank accounts, optional for custody and wallets
host_location: string; // Bank Address for bank accounts, optional for custody and wallets
node_name: string; // Account holder's legal name
node_address: string; // Account Number for bank accounts, wallet address for wallets, optional for custody
node_location: string; // Account holder's residential address for bank accounts, optional memo field for custody and wallets
node_country: string; // Account holder's residential address country code (2-letter ISO country code), optional memo field for custody and wallets
node_subaddress?: string; // Optional sub-address for wallets
iban: string; // IBAN for bank accounts
account_label: string; // Display name for beneficiary
description: string; // Free-text description of beneficiary
settlement_reference: string; // Optional settlement reference for payments
created_at: string; // Timestamp of account record creation (YYYY-MM-DDTHH:MM:SS.000Z)
updated_at: string; // Timestamp of account record update (YYYY-MM-DDTHH:MM:SS.000Z)
partner_id: number; // Internal numeric ID of white-label partner
email: string; // Email address of beneficiary
pid: string; // Alpha-numeric ID of white-label partner
partner_name: string; // White-label partner name
}Beneficiary Usage Examples
// Display beneficiary details
const beneficiary = await bcb.beneficiaries.retrieve(378);
console.log('Beneficiary Details:');
console.log(` Label: ${beneficiary.data.account_label}`);
console.log(` Type: ${beneficiary.data.account_type}`);
console.log(` Currency: ${beneficiary.data.ccy}`);
console.log(` Host: ${beneficiary.data.host_name}`);
console.log(` Partner: ${beneficiary.data.partner_name}`);
if (beneficiary.data.iban) {
console.log(` IBAN: ${beneficiary.data.iban}`);
}
if (beneficiary.data.node_address) {
console.log(` Address: ${beneficiary.data.node_address}`);
}
// Filter and analyze beneficiaries
const allBeneficiaries = await bcb.beneficiaries.list();
// Group by currency
const byCurrency = allBeneficiaries.data.reduce((acc, b) => {
acc[b.ccy] = (acc[b.ccy] || 0) + 1;
return acc;
}, {} as Record<string, number>);
console.log('Beneficiaries by currency:', byCurrency);
// Group by account type
const byType = allBeneficiaries.data.reduce((acc, b) => {
acc[b.account_type] = (acc[b.account_type] || 0) + 1;
return acc;
}, {} as Record<string, number>);
console.log('Beneficiaries by type:', byType);Payments Management (V5 API)
The SDK provides comprehensive payment functionality using the latest V5 payments endpoint with enhanced address validation and support for multiple payment schemes and currencies.
Purpose Code Validation
All payments require a valid reason code (purpose code) that complies with banking standards. The SDK validates these codes before making API calls to provide immediate feedback:
// ✅ Valid reason codes (examples)
'BKFE' // Bank loan fees
'GDSV' // Purchase/Sale of Goods and Services
'SALA' // Salary Payment
'RENT' // Rent payment
'TAXS' // Tax Payment
'SERV' // Service charges
// ... and 100+ other valid codes
// ❌ Invalid reason codes will throw an error
reason: 'invalid-code' // Error: Invalid reason code 'invalid-code'. Must be one of the following valid purpose codes: BKFE, BKIP, BKPP, ...Purpose Code Categories:
- Bank Debt:
BKFE,BKIP,BKPP - Commercial:
GDSV,SERV,SUPP,TRAD, etc. - Salary & Benefits:
SALA,BONU,COMM,PENS, etc. - Tax:
TAXS,INTX,VATX,HSTX, etc. - Utilities:
ELEC,GASB,WATR,PHON, etc. - And many more categories...
// GBP FPS Payment (Faster Payments)
const fpsPayment = await bcb.payments.createGBPFPS({
counterparty_id: 483,
sender_account_id: 378,
beneficiary_name: 'John Smith',
beneficiary_account_number: '12345678',
beneficiary_sort_code: '200000',
amount: '100.50',
reference: 'Invoice INV-2024-001',
reason: 'GDSV', // Purchase/Sale of Goods and Services
notes: 'Urgent payment'
});
// GBP CHAPS Payment (High Value)
const chapsPayment = await bcb.payments.createGBPCHAPS({
counterparty_id: 483,
sender_account_id: 378,
beneficiary_name: 'Property Holdings Ltd',
beneficiary_account_number: '87654321',
beneficiary_sort_code: '400000',
beneficiary_address_line_1: '1 Property Square',
beneficiary_city: 'London',
beneficiary_postcode: 'E14 5AB', // Mandatory for CHAPS
beneficiary_country: 'GB',
beneficiary_lei_code: 'ABCDEFGHIJKLMNOP1234', // Mandatory for CHAPS
amount: '1500000.00',
reference: 'Property Purchase',
reason: 'HLRP' // Property Loan
});
// USD Payment
const usdPayment = await bcb.payments.createUSD({
counterparty_id: 483,
sender_account_id: 378,
beneficiary_name: 'Tech Solutions Inc',
beneficiary_account_number: '123456789',
beneficiary_routing_number: '021000021',
beneficiary_address_line_1: '123 Silicon Valley Drive',
beneficiary_city: 'San Francisco',
beneficiary_country: 'US',
beneficiary_bank_name: 'Chase Bank',
beneficiary_bank_address: '270 Park Avenue, New York, NY 10017',
beneficiary_bank_country: 'US',
amount: '2500.00',
reference: 'Software License',
reason: 'SERV' // Service charges
});
// EUR Payment with IBAN
const eurPayment = await bcb.payments.createEUR({
counterparty_id: 483,
sender_account_id: 378,
beneficiary_name: 'Deutsche Manufacturing GmbH',
beneficiary_address_line_1: 'Industriestraße 45',
beneficiary_city: 'Munich',
beneficiary_country: 'DE',
beneficiary_bic: 'DEUTDEFF',
beneficiary_iban: 'DE89370400440532013000',
amount: '750.00',
reference: 'Equipment Purchase',
reason: 'GDSV' // Purchase/Sale of Goods and Services
});
// International Payment (any currency)
const chfPayment = await bcb.payments.createInternational('CHF', {
counterparty_id: 483,
sender_account_id: 378,
beneficiary_name: 'Swiss Precision AG',
beneficiary_address_line_1: 'Bahnhofstrasse 123',
beneficiary_city: 'Zurich',
beneficiary_country: 'CH',
beneficiary_bic: 'UBSWCHZH80A',
beneficiary_account_number: 'CH9300762011623852957',
amount: '500.00',
reference: 'Consulting Services',
reason: 'SERV' // Service charges
});
// Payment with existing beneficiary
const beneficiaryPayment = await bcb.payments.authorize({
counterparty_id: 483,
sender_account_id: 378,
beneficiary_account_id: 456,
ccy: 'GBP',
amount: '75.00',
reference: 'Monthly Payment',
reason: 'SERV', // Service charges
preferred_scheme: 'AUTO',
// V5 mandatory address fields
beneficiary_address_line_1: '123 Stored Address',
beneficiary_city: 'London',
beneficiary_country: 'GB'
});
// BLINC Network Payment
const blincPayment = await bcb.payments.createBLINC({
counterparty_id: 483,
sender_account_id: 378,
beneficiary_account_id: 456,
ccy: 'BTC',
amount: '0.001',
reference: 'Crypto Transfer',
reason: 'TRAD', // Commercial transaction
beneficiary_address_line_1: 'Digital Network',
beneficiary_city: 'BLINC Network',
beneficiary_country: 'XX'
});
// Internal Transfer
const internalPayment = await bcb.payments.createInternal({
counterparty_id: 483,
sender_account_id: 378,
beneficiary_account_id: 379,
ccy: 'USD',
amount: '1000.00',
reference: 'Internal Transfer',
reason: 'ACCTCASH', // Account Management
beneficiary_address_line_1: 'Internal',
beneficiary_city: 'Same Institution',
beneficiary_country: 'XX'
});Payment Schemes
The V5 payments API supports three payment schemes:
AUTO- Automatic scheme selection for external paymentsBLINC- Payments within the BLINC network (requires BLINC accounts)INTERNAL- Payments between BCB accounts of the same counterparty
Currency-Specific Requirements
The SDK automatically validates currency-specific requirements:
GBP Payments:
- FPS: Account number + sort code (under £1M)
- CHAPS: Account number + sort code + full address + postcode + LEI code (over £1M)
- SWIFT: Account number + sort code + SWIFT code (international)
USD Payments:
- Account number + routing number + bank name + bank address
EUR Payments:
- BIC + IBAN (or account number for non-IBAN countries)
Other Currencies:
- BIC + account number + full address
V5 Address Fields (Mandatory)
All V5 payments require enhanced address fields:
beneficiary_address_line_1(mandatory)beneficiary_address_line_2(optional)beneficiary_address_line_3(optional)beneficiary_city(mandatory)beneficiary_region(optional)beneficiary_postcode(mandatory for CHAPS)beneficiary_country(mandatory)beneficiary_lei_code(mandatory for CHAPS)
Payment Response
interface PaymentResponse {
endToEndIdentification: string; // Payment end-to-end ID
transactionId: string; // BCB transaction ID
nonce?: string; // Optional nonce (if provided)
response: 'Accepted' | 'Rejected'; // Payment status
}Purpose Codes
The SDK supports all standard purpose codes for payment categorization. Common examples:
GDSV- Purchase Sale of Goods and ServicesSALA- Salary PaymentRENT- Rent PaymentINSU- Insurance PremiumTAXS- Tax PaymentDIVD- Dividends
Validation and Error Handling
The SDK provides comprehensive validation:
- Required field validation
- Currency-specific field validation
- Amount format validation (decimal strings)
- CHAPS-specific requirements (postcode, LEI code)
- Scheme-specific requirements (BLINC, INTERNAL)
try {
const payment = await bcb.payments.authorize(paymentRequest);
console.log(`Payment ${payment.data[0].response}: ${payment.data[0].transactionId}`);
} catch (error) {
if (error.message.includes('Amount must be')) {
console.error('Invalid amount format');
} else if (error.message.includes('CHAPS payments require')) {
console.error('Missing CHAPS requirements');
} else {
console.error('Payment failed:', error.message);
}
}BLINC Network Management
The SDK provides comprehensive BLINC (Blockchain Interoperability Network for Commerce) functionality for managing connected BLINC members and beneficiaries:
// List BLINC beneficiaries for a specific account
const blincBeneficiaries = await bcb.blinc.listBeneficiaries(9999);
console.log(`Found ${blincBeneficiaries.data.length} BLINC beneficiaries`);
// Filter BLINC beneficiaries by currency
const gbpBlincBeneficiaries = await bcb.blinc.listBeneficiariesByCurrency(9999, 'GBP');
const eurBlincBeneficiaries = await bcb.blinc.listBeneficiaries(9999, { ccy: 'EUR' });
// Get a BLINC member by BLINC ID
const blincMember = await bcb.blinc.getMember('800999999999');
console.log(`Member: ${blincMember.data[0].name}`);
// Get single BLINC member (convenience method)
const singleMember = await bcb.blinc.getMemberSingle('800999999999');
console.log(`Member: ${singleMember.data.name} (${singleMember.data.ccy})`);
// Check if a BLINC member exists
const memberExists = await bcb.blinc.memberExists('800999999999');
if (memberExists) {
console.log('BLINC member found');
}
// Get available currencies for BLINC beneficiaries
const currencies = await bcb.blinc.getAvailableCurrencies(9999);
console.log(`Available currencies: ${currencies.join(', ')}`);
// Search BLINC beneficiaries by name
const searchResults = await bcb.blinc.searchBeneficiariesByName(9999, 'John');
const filteredSearch = await bcb.blinc.searchBeneficiariesByName(9999, 'Smith', { ccy: 'GBP' });BLINC Beneficiary Object Structure
interface BlincBeneficiary {
id: number; // Numeric internal account ID
blinc_id: string; // Numeric BLINC account ID
ccy: string; // Currency of the BLINC account
name: string; // Name of the BLINC account holder
}BLINC Member Object Structure
interface BlincMember {
id: number; // Numeric internal account ID
blinc_id: string; // Numeric BLINC account ID
ccy: string; // Currency of the BLINC account
name: string; // Name of the BLINC account holder
}BLINC Usage Examples
// Get all BLINC beneficiaries for account analysis
const accounts = await bcb.accounts.list();
const firstAccountId = accounts.data[0].id;
const allBlincBeneficiaries = await bcb.blinc.listBeneficiaries(firstAccountId);
console.log(`Total BLINC beneficiaries: ${allBlincBeneficiaries.data.length}`);
// Group BLINC beneficiaries by currency
const byCurrency = allBlincBeneficiaries.data.reduce((acc, b) => {
acc[b.ccy] = (acc[b.ccy] || 0) + 1;
return acc;
}, {} as Record<string, number>);
console.log('BLINC beneficiaries by currency:', byCurrency);
// Find specific BLINC members
for (const beneficiary of allBlincBeneficiaries.data) {
const memberDetail = await bcb.blinc.getMemberSingle(beneficiary.blinc_id);
console.log(`${memberDetail.data.name}: ${memberDetail.data.ccy}`);
}
// Currency-specific BLINC operations
const availableCurrencies = await bcb.blinc.getAvailableCurrencies(firstAccountId);
for (const currency of availableCurrencies) {
const currencyBeneficiaries = await bcb.blinc.listBeneficiariesByCurrency(firstAccountId, currency);
console.log(`${currency}: ${currencyBeneficiaries.data.length} BLINC beneficiaries`);
}
// Search and filter operations
const searchTerm = 'BLINC';
const searchResults = await bcb.blinc.searchBeneficiariesByName(firstAccountId, searchTerm);
console.log(`Found ${searchResults.data.length} BLINC beneficiaries matching "${searchTerm}"`);
// Combined search with currency filter
const gbpSearchResults = await bcb.blinc.searchBeneficiariesByName(
firstAccountId,
'Member',
{ ccy: 'GBP' }
);
console.log(`GBP BLINC members containing "Member": ${gbpSearchResults.data.length}`);BLINC Network Features
The BLINC functionality provides:
- Connected Members: List all BLINC accounts connected to your entity
- Currency Filtering: Filter BLINC beneficiaries by specific currencies
- Member Lookup: Get detailed information about specific BLINC members
- Existence Checking: Verify if a BLINC member exists before operations
- Name Search: Search BLINC beneficiaries by name with partial matching
- Currency Discovery: Get all available currencies for BLINC beneficiaries
Note: All BLINC accounts connected to your entity are returned regardless of which specific account ID was requested. The BLINC network provides interoperability between all connected members.
Beneficiary Creation (V4 API)
The SDK provides comprehensive beneficiary creation functionality using the V4 accounts endpoint. The beneficiaries service now includes both listing and creation methods for a complete beneficiary management solution:
// Create a GBP beneficiary with Account Number + Sort Code
const gbpBeneficiary = await bcb.beneficiaries.createGBP({
counterparty_id: 483,
cid: "CX00000101",
name: "John Smith",
host_name: "Barclays Bank",
sort_code: "200000",
account_number: "12345678",
node_name: "John Smith",
node_location_line_1: "123 Main Street",
node_location_city: "London",
node_location_postcode: "SW1A 1AA",
node_type: "individual",
email: "[email protected]"
});
// Create a USD beneficiary with routing number
const usdBeneficiary = await bcb.beneficiaries.createUSD({
counterparty_id: 483,
cid: "CX00000101",
name: "Jane Doe",
host_name: "Bank of America",
routing_number: "121000358",
account_number: "987654321",
node_name: "Jane Doe",
node_location_line_1: "456 Wall Street",
node_location_city: "New York",
node_location_postcode: "10005",
node_type: "individual",
email: "[email protected]"
});
// Create an IBAN beneficiary (EUR and other IBAN countries)
const eurBeneficiary = await bcb.beneficiaries.createIBAN({
counterparty_id: 483,
cid: "CX00000101",
name: "Marie Dubois",
ccy: "EUR",
host_name: "BNP Paribas",
host_location: "Paris, France",
host_country: "FR",
node_name: "Marie Dubois",
node_location_line_1: "456 Rue de Rivoli",
node_location_city: "Paris",
node_location_postcode: "75001",
node_country: "FR",
node_type: "individual",
iban: "FR1420041010050500013M02606", // Valid French IBAN
bic: "BNPAFRPPXXX"
});
// Create a cryptocurrency wallet beneficiary
const btcBeneficiary = await bcb.beneficiaries.createWallet({
counterparty_id: 483,
cid: "CX00000101",
name: "Crypto Wallet",
ccy: "BTC",
node_name: "Bitcoin Wallet",
wallet_address: "3LxDswEWKC3mJewRYs44xr3qNBqXMwhszo",
node_location_line_1: "789 Tech Street",
node_location_city: "San Francisco",
node_location_postcode: "94105",
node_country: "US",
node_type: "individual"
});
// Generic beneficiary creation with full control
const customBeneficiary = await bcb.beneficiaries.create({
counterparty_id: 483,
cid: "CX00000101",
name: "Custom Beneficiary",
account_type: "Bank",
ccy: "CAD",
host_name: "Royal Bank of Canada",
host_hub: "003200233", // Canadian routing number
host_country: "CA",
node_name: "Custom User",
node_address: "123456789",
node_location_line_1: "123 Maple Street",
node_location_city: "Toronto",
node_location_postcode: "M5V 3A8",
node_country: "CA",
node_type: "individual",
bic: "ROYCCAT2XXX",
account_label: "Custom User - CAD",
email: "[email protected]",
bcb_controlled: 1,
is_beneficiary: 1
});Beneficiary Creation Convenience Methods
The beneficiaries service provides country and currency-specific convenience methods:
bcb.beneficiaries.createGBP()- For UK bank accounts with sort codesbcb.beneficiaries.createUSD()- For US bank accounts with routing numbersbcb.beneficiaries.createIBAN()- For IBAN-based bank accounts (EUR and other IBAN countries)bcb.beneficiaries.createWallet()- For cryptocurrency wallet addressesbcb.beneficiaries.create()- Generic method with full control over all parameters
Validation and Requirements
The SDK automatically validates beneficiary creation requests based on:
- Account Type: Bank accounts require either IBAN or account number
- Currency Requirements: USD in US requires routing number, GBP in UK requires sort code
- Address Requirements: GBP accounts require full address for CHAPS payments
- Node Type: Must be either "individual" or "corporate"
- Required Flags:
bcb_controlledandis_beneficiarymust be 1
Create Beneficiary Response
interface CreateBeneficiaryResponse {
id: number; // Unique beneficiary ID of the created account
}Note: The V4 accounts endpoint returns only the ID of the created beneficiary account. To retrieve the full beneficiary details, use the beneficiaries list endpoint with the returned ID.
Country-Specific Examples
// UK GBP Account with Sort Code
const ukAccount = await bcb.beneficiaries.createGBP({
counterparty_id: 483,
cid: "CX00000101",
name: "UK Beneficiary",
host_name: "HSBC",
sort_code: "400000", // UK sort code
account_number: "12345678",
node_name: "John Smith",
node_location_line_1: "123 High Street",
node_location_city: "London",
node_location_postcode: "SW1A 1AA", // Required for CHAPS
node_type: "individual"
});
// US USD Account with Routing Number
const usAccount = await bcb.beneficiaries.createUSD({
counterparty_id: 483,
cid: "CX00000101",
name: "US Beneficiary",
host_name: "Chase Bank",
routing_number: "021000021", // US routing number
account_number: "123456789",
node_name: "Jane Doe",
node_location_line_1: "456 Broadway",
node_location_city: "New York",
node_location_postcode: "10013",
node_type: "individual"
});
// EU EUR Account with IBAN
const euAccount = await bcb.beneficiaries.createIBAN({
counterparty_id: 483,
cid: "CX00000101",
name: "EU Beneficiary",
ccy: "EUR",
host_name: "Deutsche Bank",
host_country: "DE",
node_name: "Hans Mueller",
node_location_line_1: "Hauptstraße 123",
node_location_city: "Frankfurt",
node_location_postcode: "60311",
node_country: "DE",
node_type: "individual",
iban: "DE89370400440532013000", // German IBAN
bic: "DEUTDEFFXXX"
});
// Bitcoin Wallet
const btcWallet = await bcb.beneficiaries.createWallet({
counterparty_id: 483,
cid: "CX00000101",
name: "BTC Wallet",
ccy: "BTC",
node_name: "Bitcoin Wallet",
wallet_address: "3LxDswEWKC3mJewRYs44xr3qNBqXMwhszo",
node_location_line_1: "789 Crypto Street",
node_location_city: "San Francisco",
node_location_postcode: "94105",
node_country: "US",
node_type: "individual"
});VOP (Verification of Payee) Management
The SDK provides comprehensive VOP functionality for approving and canceling payments where the beneficiary name does not match the name on the account. This is essential for compliance with banking regulations and fraud prevention.
Note: VOP is part of the payments module and uses the Client API endpoint (client-api.bcb.group) rather than the standard API endpoint.
// Approve a payment for verification of payee
const approveResult = await bcb.payments.vop.approve(123, 'E2E123456789');
console.log(`Payment approved: ${approveResult.status}`); // 202 - Accepted
// Cancel a payment for verification of payee
const cancelResult = await bcb.payments.vop.cancel(123, 'E2E987654321');
console.log(`Payment cancelled: ${cancelResult.status}`); // 202 - AcceptedVOP Methods
// Approve unverified payment
const approveResult = await bcb.payments.vop.approve(accountId, e2eId);
// Cancel unverified payment
const cancelResult = await bcb.payments.vop.cancel(accountId, e2eId);VOP Response Codes
The VOP endpoints return specific HTTP status codes:
- 202 - Success (payment approved/cancelled)
- 401 - Unauthorized (invalid credentials)
- 404 - No unverified payment found for the account with the given end-to-end ID
- 409 - The payment is not unverified (already processed)
Error Handling
try {
const result = await bcb.payments.vop.approve(123, 'E2E123456789');
console.log('Payment approved successfully');
} catch (error) {
if (error.message.includes('404')) {
console.log('No unverified payment found for this account with the given end-to-end ID');
} else if (error.message.includes('409')) {
console.log('The payment is not unverified');
} else if (error.message.includes('401')) {
console.log('Unauthorized - check your credentials');
} else {
console.error('VOP operation failed:', error.message);
}
}Batch VOP Operations
// Process multiple VOP approvals
const payments = [
{ accountId: 123, e2eId: 'E2E111111111' },
{ accountId: 123, e2eId: 'E2E222222222' },
{ accountId: 456, e2eId: 'E2E333333333' },
];
const results = await Promise.allSettled(
payments.map(payment =>
bcb.payments.vop.approve(payment.accountId, payment.e2eId)
)
);
results.forEach((result, index) => {
const payment = payments[index];
if (result.status === 'fulfilled') {
console.log(`✅ Payment ${payment.e2eId} approved successfully`);
} else {
console.log(`❌ Payment ${payment.e2eId} failed:`, result.reason.message);
}
});VOP with Retry Logic
const retryApprove = async (accountId: number, e2eId: string, maxRetries = 3) => {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const result = await bcb.payments.vop.approve(accountId, e2eId);
console.log(`✅ Payment approved on attempt ${attempt}`);
return result;
} catch (error) {
console.log(`❌ Attempt ${attempt} failed:`, error.message);
if (attempt === maxRetries) {
throw error;
}
// Wait before retry (exponential backoff)
const delay = Math.pow(2, attempt) * 1000;
console.log(`⏳ Waiting ${delay}ms before retry...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
};
try {
await retryApprove(123, 'E2E444444444');
} catch (error) {
console.log('❌ All retry attempts failed:', error.message);
}Virtual Accounts Management (V2 Client API)
The SDK provides comprehensive virtual accounts functionality for creating virtual accounts for individuals and companies with different currency requirements (EUR with IBAN/BIC, GBP with sort code/account number).
Note: Virtual accounts use the Client API endpoint (client-api.bcb.group) rather than the standard API endpoint.
// Create mixed EUR and GBP virtual accounts
const mixedOwners = [
{
correlationId: "550e8400-e29b-41d4-a716-446655440001", // UUID format required
name: "Hans Mueller",
addressLine1: "Friedrichstrasse",
addressLine2: "100",
city: "Berlin",
region: "Berlin",
postcode: "10115",
country: "DE",
nationality: "DE",
dateOfBirth: "1985-03-15",
isIndividual: true,
iban: "DE53202208000099106929",
bicSwift: "MHSBDEHBXXX"
},
{
correlationId: "550e8400-e29b-41d4-a716-446655440002", // UUID format required
name: "ACME Trading Ltd",
addressLine1: "One London Wall",
addressLine2: "6th Floor",
city: "London",
region: "Greater London",
postcode: "EC2Y 5EB",
country: "GB",
nationality: "GB",
registrationNumber: "AB123456",
isIndividual: false,
accountNumber: "55555555",
sortCode: "202015"
}
];
const segregatedAccountId = 123; // Your segregated account ID
const response = await bcb.virtualAccounts.create(segregatedAccountId, {
owners: mixedOwners
});
console.log(`Status: ${response.status}`); // 202 - Accepted
console.log(`Response: ${JSON.stringify(response.data)}`);Convenience Methods
The virtual accounts service provides convenient methods for specific use cases:
// Create virtual accounts for individuals only
const individuals = [
{
correlationId: "550e8400-e29b-41d4-a716-446655440003", // UUID format required
name: "Alice Johnson",
addressLine1: "123 High Street",
city: "Manchester",
postcode: "M1 1AA",
country: "GB",
nationality: "GB",
dateOfBirth: "1988-11-03",
accountNumber: "12345678",
sortCode: "123456"
}
];
const individualResponse = await bcb.virtualAccounts.createForIndividuals(
segregatedAccountId,
individuals
);
// Create virtual accounts for companies only
const companies = [
{
correlationId: "550e8400-e29b-41d4-a716-446655440004", // UUID format required
name: "Digital Solutions Ltd",
addressLine1: "Tech Park",
addressLine2: "Building A",
city: "Cambridge",
postcode: "CB1 2AB",
country: "GB",
nationality: "GB",
registrationNumber: "12345678",
accountNumber: "87654321",
sortCode: "654321"
}
];
const companyResponse = await bcb.virtualAccounts.createForCompanies(
segregatedAccountId,
companies
);
// Create virtual accounts without bank details (receive-only)
const noBankDetails = [
{
correlationId: "550e8400-e29b-41d4-a716-446655440005", // UUID format required
name: "Startup Company Ltd",
addressLine1: "Innovation Hub",
city: "Bristol",
postcode: "BS1 1AA",
country: "GB",
nationality: "GB",
registrationNumber: "STARTUP123",
isIndividual: false
}
];
const noBankResponse = await bcb.virtualAccounts.createWithoutBankDetails(
segregatedAccountId,
noBankDetails
);
// Currency-specific convenience methods
const gbpOwners = [
{
correlationId: "550e8400-e29b-41d4-a716-446655440006", // UUID format required
name: "GBP Account Holder",
addressLine1: "London Street",
city: "London",
postcode: "SW1A 1AA",
country: "GB",
nationality: "GB",
dateOfBirth: "1990-01-01",
isIndividual: true,
accountNumber: "11111111",
sortCode: "111111"
}
];
const gbpResponse = await bcb.virtualAccounts.createGBP(segregatedAccountId, gbpOwners);
const eurOwners = [
{
correlationId: "550e8400-e29b-41d4-a716-446655440007", // UUID format required
name: "EUR Account Holder",
addressLine1: "Berlin Strasse",
city: "Berlin",
postcode: "10115",
country: "DE",
nationality: "DE",
registrationNumber: "DE123456",
isIndividual: false,
iban: "DE89370400440532013000",
bicSwift: "COBADEFFXXX"
}
];
const eurResponse = await bcb.virtualAccounts.createEUR(segregatedAccountId, eurOwners);Virtual Account Owner Object Structure
interface VirtualAccountOwner {
correlationId: string; // Unique identifier for this owner (must be valid UUID format)
name: string; // Legal name of the account holder
addressLine1: string; // Primary address line (mandatory)
addressLine2?: string; // Secondary address line (optional)
addressLine3?: string; // Tertiary address line (optional)
city: string; // City (mandatory)
region?: string; // Region/state (optional)
postcode: string; // Postal/ZIP code (mandatory)
country: string; // 2-letter country code (mandatory)
nationality: string; // 2-letter nationality code (mandatory)
isIndividual: boolean; // true for individuals, false for companies
// For individuals only
dateOfBirth?: string; // YYYY-MM-DD format (required for individuals)
// For companies only
registrationNumber?: string; // Company registration number (required for companies)
// Bank details (optional - can create without for receive-only accounts)
iban?: string; // International Bank Account Number
bicSwift?: string; // Bank Identifier Code / SWIFT code
// GBP specific fields
accountNumber?: string; // 8-digit UK account number
sortCode?: string; // 6-digit UK sort code
}Virtual Accounts Features
- Mixed Owner Types: Create accounts for both individuals and companies in a single request
- Currency Support: EUR (IBAN/BIC) and GBP (sort code/account number) with automatic validation
- Receive-Only Accounts: Create accounts without bank details for incoming payments only
- Bulk Creation: Up to 1000 owners per request for efficient bulk operations
- Account Listing: List and search virtual accounts with pagination support
- Account Closure: Close virtual accounts by IBAN when no longer needed
- Complete Lifecycle: Create → List → Find virtual IBAN → Close workflow
- Comprehensive Validation: Client-side validation of all required fields and formats
- Convenience Methods: Currency and type-specific methods for common use cases
Requirements and Validation
Individual Accounts:
dateOfBirthis required (YYYY-MM-DD format)registrationNumbershould not be provided
Company Accounts:
registrationNumberis requireddateOfBirthshould not be provided
GBP Bank Details:
accountNumbermust be 8 digitssortCodemust be 6 digits- Both are required together or both omitted
EUR Bank Details:
ibanmust be valid IBAN format (2 letters + 2 digits + up to 30 alphanumeric)bicSwiftmust be valid BIC format (8 or 11 characters)
Address Requirements:
countryandnationalitymust be 2-letter ISO country codesaddressLine1,city, andpostcodeare mandatoryaddressLine2,addressLine3, andregionare optional
Error Handling
The SDK provides comprehensive validation before making API calls:
try {
const response = await bcb.virtualAccounts.create(accountId, { owners });
console.log(`Created ${owners.length} virtual accounts successfully`);
} catch (error) {
if (error.message.includes('correlationId is required')) {
console.error('Missing correlation ID');
} else if (error.message.includes('Maximum 1000 owners allowed')) {
console.error('Too many owners in request');
} else if (error.message.includes('dateOfBirth is required for individuals')) {
console.error('Individual missing date of birth');
} else if (error.status === 404) {
console.error('Segregated account not found');
} else {
console.error('Virtual account creation failed:', error.message);
}
}
// Close a virtual account
try {
const closeResponse = await bcb.virtualAccounts.close(accountId, "GB33BUKB20201555555555");
console.log('Virtual account closed successfully');
} catch (error) {
if (error.status === 404) {
console.error('Virtual account or IBAN not found');
} else {
console.error('Virtual account closure failed:', error.message);
}
}Event Monitoring
// Monitor requests and responses
bcb.on('request', ({ request }) => {
console.log('Request:', request.method, request.url);
});
bcb.on('response', ({ response }) => {
console.log('Response:', response.status, response.requestId);
});
bcb.on('error', ({ error }) => {
console.error('Error:', error.message);
});🔧 Development
Building
npm run build # Build both CJS and ESM
npm run build:cjs # CommonJS build
npm run build:esm # ES Modules buildCode Quality
npm run lint # ESLint
npm run lint:fix # Fix linting issues
npm run format # Prettier formatting
npm run typecheck # TypeScript checking for src/ (also runs in CI before build)
npm run typecheck:test # TypeScript checking for tests/ + src/Testing Development
The testing infrastructure is designed to be highly expandable:
Adding New Tests
// tests/acceptance/my-feature.test.ts
import { createTestContext, skipIfConfigInvalid } from '../helpers/test-utils';
describe('My Feature Tests', () => {
let testContext: ReturnType<typeof createTestContext>;
beforeEach(() => {
if (skipIfConfigInvalid()) return;
testContext = createTestContext({ test: 'my-feature' });
});
it('should test real API functionality', async () => {
if (skipIfConfigInvalid()) {
console.log('⏭️ Skipping: No valid test configuration');
return;
}
const { sdk } = testContext;
// Your test code here - runs against real API
});
});Custom Test Utilities
import { TestDataGenerator, retry, wait } from '../helpers/test-utils';
// Generate test data
const testUser = TestDataGenerator.testObject({
email: TestDataGenerator.randomEmail()
});
// Retry with backoff
const result = await retry(() => sdk.get('/endpoint'), 3);
// Rate limiting
await wait(1000);Performance Testing
import { testUtils } from '../helpers/test-utils';
testUtils.performance.start('operation');
await sdk.post('/endpoint', data);
const duration = testUtils.performance.end('operation');
expect(duration).toBeLessThan(5000);Test Environment Settings
The framework automatically adapts to different environments:
- Development: Lenient timeouts, detailed logging
- Staging: Production-like settings, real data validation
- Production: Conservative timeouts, minimal test impact
📊 Test Reports
Tests generate comprehensive reports including:
- ✅ Pass/Fail Status - Detailed test results
- ⏱️ Performance Metrics - Request timing and throughput
- 🔍 Error Analysis - Real API error response validation
- 📈 Coverage Reports - Code coverage analysis
- 🌍 Environment Info - Test configuration and context
🔗 API Compatibility
Based on the BCB API OpenAPI specification:
Authentication Endpoint
- POST
/auth/oauth/token- OAuth2 client credentials flow
Accounts Endpoints
- GET
/v3/accounts- List accounts with optional filtering and pagination- Query Parameters:
counterparty_id- Filter by counterparty IDlimit- Limit result set for server-side pagingpageToken- Offset result set when pagingid- Return single result with matching account ID
- Query Parameters:
Balances Endpoints
- GET
/v3/balances/{account_id}- Get balance for a specific account- Path Parameters:
account_id- Account ID (numeric or string)
- Query Parameters:
dateTo- Get end-of-day balance for specific date (YYYY-MM-DD format)
- Path Parameters:
Transactions Endpoints
GET
/v3/accounts/{account_id}/transactions- List transactions for a specific account- Path Parameters:
account_id- Account ID (numeric only)
- Query Parameters:
dateFrom- Start date for filtering (YYYY-MM-DD format)dateTo- End date for filtering (YYYY-MM-DD format)limit- Limit result set for server-side pagingpageToken- Offset result set when paging
- Path Parameters:
GET
/v3/accounts/{account_id}/transactions/{tx_id}- Get transaction detail by ID- Path Parameters:
account_id- Account ID (numeric or string)tx_id- Transaction ID (unique code)
- Path Parameters:
Beneficiaries Endpoints
- GET
/v3/beneficiaries- List beneficiaries with optional filtering and pagination- Query Parameters:
limit- Limit result set for server-side pagingpageToken- Offset result set when paging
- Query Parameters:
BLINC Network Endpoints
GET
/v3/accounts/{account_id}/blinc-beneficiaries- List BLINC beneficiaries for an account- Path Parameters:
account_id- BLINC account ID of counterparty requesting connected BLINC members list
- Query Parameters:
ccy- Restrict response to BLINC accounts with matching currency (ISO 4217 format)
- Path Parameters:
GET
/v3/blinc-accounts/{blinc_id}- Get BLINC member by BLINC ID- Path Parameters:
blinc_id- BLINC ID of another BLINC member (numeric)
- Path Parameters:
Payments Endpoints (V5 API)
- POST
/v5/payments/authorise- Authorize payment with enhanced address fields (V5)- Request Body: PaymentRequest object with:
- Required:
counterparty_id,sender_account_id,ccy,amount,reference,reason,preferred_scheme - V5 Mandatory Address:
beneficiary_address_line_1,beneficiary_city,beneficiary_country - Beneficiary: Either
beneficiary_account_idOR beneficiary details (beneficiary_name, banking details) - Currency Specific: GBP requires sort code, USD requires routing number, EUR requires BIC
- CHAPS Specific:
beneficiary_postcodeandbeneficiary_lei_codemandatory for high-value GBP payments - Schemes:
AUTO(external),BLINC(network),INTERNAL(same counterparty)
- Required:
- Request Body: PaymentRequest object with:
Beneficiary Creation Endpoints (V4 API)
- POST
/v4/accounts- Create beneficiary account with enhanced address fields- Request Body: CreateBeneficiaryRequest object with:
- Required:
counterparty_id,cid,name,account_type,ccy,node_name,node_type,bcb_controlled: 1,is_beneficiary: 1 - Account Type Specific: Bank accounts require IBAN or account number, wallets require wallet address
- Address Fields: Enhanced V4 address structure with separate fields for line 1-3, city, region, postcode
- Currency Specific: USD in US requires routing number, GBP in UK requires sort code and full address for CHAPS
- Required:
- Request Body: CreateBeneficiaryRequest object with:
VOP (Verification of Payee) Endpoints (Client API)
POST
/v1/accounts/{accountId}/payments/{e2eId}/verification-of-payee/approve- Approve a payment where the beneficiary name does not match the name on the account- Path Parameters:
accountId- The account ID (numeric)e2eId- The end-to-end ID of the payment (string)
- Response: 202 (Accepted), 401 (Unauthorized), 404 (No unverified payment found), 409 (Payment is not unverified)
- Note: Uses Client API endpoint (
client-api.bcb.group)
- Path Parameters:
POST
/v1/accounts/{accountId}/payments/{e2eId}/verification-of-payee/cancel- Cancel a payment where the beneficiary name does not match the name on the account- Path Parameters:
accountId- The account ID (numeric)e2eId- The end-to-end ID of the payment (string)
- Response: 202 (Accepted), 401 (Unauthorized), 404 (No unverified payment found), 409 (Payment is not unverified)
- Note: Uses Client API endpoint (
client-api.bcb.group)
- Path Parameters:
Virtual Accounts Endpoints (Client API)
POST
/v2/accounts/{accountId}/virtual- Create virtual accounts for given owners (V2 Client API endpoint)- Path Parameters:
accountId- The account id for the segregated account (numeric)
- Request Body: Array of VirtualAccountOwner objects with:
- Required:
correlationId(UUID format),name,addressLine1,city,postcode,country,nationality,isIndividual - Individual Specific:
dateOfBirth(YYYY-MM-DD format) required forisIndividual: true - Company Specific:
registrationNumberrequired forisIndividual: false - Optional Bank Details:
iban+bicSwiftfor EUR,accountNumber+sortCodefor GBP (owner's external bank details) - Address Fields:
addressLine2,addressLine3,regionoptional - Limits: Maximum 1000 owners per request
- Required:
- Path Parameters:
GET
/v1/accounts/{accountId}/virtual/all-account-data- List virtual accounts (V1 Client API endpoint)- Path Parameters:
accountId- The account id for the segregated account (numeric)
- Query Parameters:
pageIndex- The page offset (optional, default: 0)pageSize- The limit of results (optional, default: 1000)
- Response: Virtual accounts with their generated IBANs and status
- Path Parameters:
POST
/v1/accounts/{accountId}/virtual/{iban}/close- Close virtual account by IBAN (V1 Client API endpoint)- Path Parameters:
accountId- The account id for the segregated account (numeric)iban- The IBAN of the virtual account to close (generated virtual IBAN, not owner's external IBAN)
- Response: 202 (Accepted) or 404 (Account/IBAN not found)
- Path Parameters:
Response Format
All API responses follow the standard BCB format with:
data- Response payloadstatus- HTTP status codeheaders- Response headersrequestId- Unique request identifier
🛡️ Security
- ✅ Credentials stored securely in environment variables
- ✅ No hardcoded secrets in code
- ✅ Token automatic refresh and caching
- ✅ Proper error handling without data leakage
📚 Additional Resources
- Testing Guide - Comprehensive testing documentation
- Accounts Usage Example - Complete accounts functionality demo
- Balances Usage Example - Complete balances functionality demo
- Transactions Usage Example - Complete transactions functionality demo
- Payments Usage Example - Complete payments functionality demo
- VOP Usage Example - Complete VOP functionality demo
- Virtual Accounts Usage Example - Complete virtual accounts functionality demo
- BCB API Documentation - Official API docs
- TypeScript Guide - TypeScript documentation
🤝 Contributing
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass:
npm test - Submit a pull request
📄 License
MIT License - see LICENSE file for details.
Built with ❤️ for developers who need reliable, well-tested SDKs that work against real APIs.
