The virtual account number from which funds will be withdrawn.
- Withdraw funds (External V2)
Bermuda Commercial Bank RESTful Open Banking API Implementation (v1)
The Bermuda Commercial Bank (BCB) RESTful Open Banking API provides secure, programmatic access to BCB's banking services, enabling developers to integrate financial services into their applications.
- Account details retrieval
- Internal transfers
- Payments (Swift)
- Virtual Accounts
- Transaction information access
- Robust security and compliance
- Comprehensive documentation
Request
Corporate Client initiates External Withdrawal request to BCB to debit Virtual Account and credit to External Beneficiary Account. This endpoint allows clients to withdraw funds from a virtual account to an external beneficiary account.
- Withdraws funds from a virtual account to an external beneficiary account
- Supports idempotency to prevent duplicate transactions
- Supports both JSON and CSV response formats
- Automatic virtual account number validation
- Includes comprehensive beneficiary and ordering customer information for external transfers
- Supports both the existing same-currency payload and the additive cross-currency FX payload
Use one of the following request shapes:
Existing format - same-currency:
{
"debitCurrency": "USD",
"creditAmount": {
"currency": "USD",
"amount": 2500
}
}Additive format - cross-currency FX:
{
"debitAmount": {
"currency": "USD",
"amount": 2500
},
"creditAmount": {
"currency": "HKD"
}
}Provide
debitAmount(currency and amount) when you want the debit side to be authoritative.Provide only
creditAmount.currencyin that case; the bank assigns the exchange rate and final credited amount before forwarding to the beneficiary.If
debitAmountis omitted, the existingdebitCurrency+creditAmount(currency + amount) format applies with no change to current behaviour.debitCurrencyis not deprecated and remains fully supported.Both payload formats are accepted and return a successful response.
- The virtualAccountId in the route parameter identifies the source virtual account
- The request body specifies the destination external beneficiary account via
creditorAccount.identification - Ensure the virtual account has sufficient funds before making the request
- Virtual accounts must be in an active state to process withdrawals
- External transfers require additional beneficiary information for compliance
Virtual account withdrawals transfer funds from virtual accounts to external beneficiary accounts:
Virtual Account → External Beneficiary AccountWhen processing an external withdrawal transfer, funds flow from the virtual account to the external beneficiary account.
External transfers require additional information for regulatory compliance:
- debitCurrency: Currency to debit from the virtual account (e.g., "USD")
- creditAmount: Amount and currency to credit externally (e.g., { amount: "2500.00", currency: "USD" })
- debtor: Ordering customer name or reference (required, max 35 characters)
- debtorAgent: Ordering bank/agent identifier (free text, max 35 characters) - Optional
- creditorAccount.identification: External beneficiary account identifier (required, max 35 characters)
- creditorAccount.name / additionalInformation: Beneficiary name and auxiliary details (optional)
- chargesType: Who bears charges (e.g., OUR, BEN, SHA)
- creditorAgent: Beneficiary bank info (identification, name, additionalInformation)
- intermediaryAgent (optional): Intermediary bank info (identification, name, additionalInformation)
- remittanceInformation (optional): Unstructured remittance lines
- If
creditorAgent.identification(BIC/bank identifier) is provided,creditorAgent.nameandcreditorAgent.additionalInformationare optional and may be omitted. - If
creditorAgent.identificationis not provided, supplycreditorAgent.nameandcreditorAgent.additionalInformationto identify the beneficiary bank.
The API supports idempotency through the optional Idempotency-Key header:
- If no idempotency key is provided, the request is processed normally (duplicates are possible)
- If a valid UUID idempotency key is provided for a new transaction, the system stores the key and associates it with the transaction results
- If the same idempotency key is received again for the same endpoint/action, the system returns the previously stored response
- Idempotency keys are user-specific - different users with the same keys don't share cached responses
- The idempotency key must be a valid UUID format (e.g., "123e4567-e89b-12d3-a456-426614174000").
Clients must use the HTTP Accept header to indicate the desired response format:
- Set
Accept: application/jsonfor JSON responses (default) - Set
Accept: text/csvfor CSV responses If the Accept header is omitted,application/jsonis assumed.
All API requests use the versioned base URL:
https://api.bcb.bm/v1/virtual-accounts/{virtualAccountId}/withdrawals/external
async function processExternalWithdrawal() {
try {
const virtualAccountId = "1000320575";
const response = await fetch(`https://api.bcb.bm/v1/virtual-accounts/${virtualAccountId}/withdrawals/external`, {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json',
'Accept': 'application/json',
'Idempotency-Key': '123e4567-e89b-12d3-a456-426614174000' // Optional
},
body: JSON.stringify({
debitCurrency: "USD",
creditAmount: {
currency: "USD",
amount: "2500.00"
},
debtor: "John Smith Corporation",
debtorAgent: "CHASUS33XXX",
creditorAccount: {
identification: "GB29NWBK60161331926819",
name: "Acme Manufacturing Ltd",
additionalInformation: [
"123 Business Street",
"London, UK SW1A 1AA"
]
},
chargesType: "OUR",
creditorAgent: {
identification: "NWBKGB2L",
name: "NatWest Bank",
additionalInformation: [
"250 Bishopsgate",
"London, UK EC2M 4AA"
]
},
intermediaryAgent: {
identification: "CHASUS33",
name: "JPMorgan Chase Bank",
additionalInformation: [
"383 Madison Avenue",
"New York, NY 10017"
]
},
remittanceInformation: [
"Withdrawal from Virtual Account VA-2024-001",
"Transfer to external beneficiary account",
"Reference: WD-2024-789456"
]
})
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(`External withdrawal transfer failed: ${JSON.stringify(errorData)}`);
}
const data = await response.json();
console.log('External withdrawal transfer result:', data);
// Example processing of the returned object
const { id, status, uniqueIdentifier, details, linkedActivities } = data;
const { debitAmount, valueDate, childTransactionId, creditAmountCurrency, debitAccountNumber, creditAccountNumber } = details;
// Log the main transfer details
console.log('Transaction ID:', id);
console.log('Status:', status);
console.log('Unique Identifier:', uniqueIdentifier);
console.log('Debit Amount:', debitAmount.amount, debitAmount.currency);
console.log('Value Date:', valueDate);
console.log('Child Transaction ID:', childTransactionId);
console.log('Credit Amount Currency:', creditAmountCurrency);
// Process debit account information (virtual account)
console.log('Debit Account Number:', debitAccountNumber.number);
// Process credit account information (external beneficiary account)
console.log('Credit Account Number:', creditAccountNumber.number);
// Process linked activities
linkedActivities.forEach(activity => {
console.log('Linked Activity ID:', activity.id);
console.log('Linked Activity Transaction Status:', activity.transactionStatus);
console.log('Linked Activity Status:', activity.status);
console.log('Linked Activity Unique Identifier:', activity.uniqueIdentifier);
const { arrangementId, activityId, productId, currencyId, effectiveDate } = activity.activityDetails;
console.log('Linked Activity Arrangement ID:', arrangementId);
console.log('Linked Activity Activity ID:', activityId);
console.log('Linked Activity Product ID:', productId);
console.log('Linked Activity Currency ID:', currencyId);
console.log('Linked Activity Effective Date:', effectiveDate);
});
// Final status logging
if (status === 'success') {
console.log('The external withdrawal was successful.');
} else {
console.log('The external withdrawal failed:', status);
}
} catch (error) {
console.error('Error processing external withdrawal:', error);
}
}
// Example usage:
processExternalWithdrawal();Required Permission: withdraw-virtual-account
This endpoint requires the permission claim withdraw-virtual-account to be present in the JWT token. These permissions are embedded in the token during the authentication process and cannot be modified afterward. The token must be obtained with the appropriate permissions to access this endpoint.
Payload containing external withdrawal transfer details. For FX cross-currency, optional debitAmount (with creditAmount currency only) may be sent.
The currency code for the debit amount (e.g., "USD", "EUR"). Exactly 3 letters (ISO 4217).
The account number to which funds will be credited (destination account). Max length: 36 characters.
The ordering customer information or reference Max length: 35 characters.
The ordering customer agent (e.g., bank identifier code). Max length: 35 characters.
Unambiguous identification of the account of the creditor to which a credit entry will be posted as a result of the payment transaction.
Specifies which party/parties will bear the charges associated with the processing of the transaction, e.g. 'OUR' Max length: 3 characters.
Remittance Information. Limit: up to 4 lines; each line max 35 characters.
- Mock serverhttps://developers.bcb.bm/_mock/apis/open-banking-api/open-banking-api/v1/virtual-accounts/{virtualAccountId}/withdrawals/external
- UAT Environment - Used for testing and integration purposeshttps://api-uat.bcb.bm/v1/virtual-accounts/{virtualAccountId}/withdrawals/external
- Production Environment - Live environment for production usehttps://api.bcb.bm/v1/virtual-accounts/{virtualAccountId}/withdrawals/external
- curl
- JavaScript
- Node.js
- Python
- Java
- C#
- PHP
- Go
- Ruby
- R
- Payload
curl -i -X POST \
'https://developers.bcb.bm/_mock/apis/open-banking-api/open-banking-api/v1/virtual-accounts/[object Object]/withdrawals/external' \
-H 'Authorization: Bearer <YOUR_jwt_HERE>' \
-H 'Content-Type: application/json' \
-d '{
"debitAmount": {
"currency": "USD",
"amount": 2500
},
"creditAmount": {
"currency": "HKD"
},
"debtor": "John Smith Corporation",
"debtorAgent": "CHASUS33XXX",
"creditorAccount": {
"identification": "GB29NWBK60161331926819",
"name": "Acme Manufacturing Ltd",
"additionalInformation": [
"123 Business Street",
"London, UK SW1A 1AA"
]
},
"chargesType": "OUR",
"creditorAgent": {
"identification": "NWBKGB2L",
"name": "NatWest Bank",
"additionalInformation": [
"250 Bishopsgate",
"London, UK EC2M 4AA"
]
},
"intermediaryAgent": {
"identification": "CHASUS33",
"name": "JPMorgan Chase Bank",
"additionalInformation": [
"383 Madison Avenue",
"New York, NY 10017"
]
},
"remittanceInformation": [
"Withdrawal from Virtual Account VA-2024-001",
"Transfer to external beneficiary account",
"Reference: WD-2024-789456"
]
}'The withdrawal transfer was processed successfully.
The current processing status of the transaction, e.g. Completed, Pending, Failed
List of related financial activities
The current processing status of the transaction.
A unique identifier specific to this instance of the activity.
Unique identifier for the arrangement associated with this activity.
Identifier for the type of activity.
Product identifier related to the activity.
{ "id": "FT252324K67K", "status": "success", "uniqueIdentifier": "IRFX252332872527361.00", "details": { "creditAmount": { … }, "debitAmountCurrency": "USD", "debitAccountNumber": { … }, "creditAccountNumber": { … }, "valueDate": "2025-08-20T07:36:00.0000000Z" }, "linkedActivities": [] }
Request
Corporate Client initiates External Withdrawal request to BCB to debit Virtual Account and credit to External Beneficiary Account. This endpoint allows clients to withdraw funds from a virtual account to an external beneficiary account.
V2 difference: The debtor field is a structured object ({ name, additionalInformation[] }) instead of the v1 plain string. All other fields, behaviour, response shape, idempotency, and content negotiation are identical to v1.
- Withdraws funds from a virtual account to an external beneficiary account
- Supports idempotency to prevent duplicate transactions
- Supports both JSON and CSV response formats
- Automatic virtual account number validation
- Includes comprehensive beneficiary and ordering customer information for external transfers
- Supports both the existing same-currency payload and the additive cross-currency FX payload
- V2: Structured debtor with name and up to 3 address lines
The debtor field must be an object containing the ordering customer name and optional address lines:
{
"debtor": {
"name": "John Smith Corporation",
"additionalInformation": [
"123 Business Street",
"London, UK SW1A 1AA"
]
}
}debtor.name: Required, max 35 charactersdebtor.additionalInformation: Optional, up to 3 lines, each max 35 characters
Use one of the following request shapes:
Existing format - same-currency:
{
"debitCurrency": "USD",
"creditAmount": {
"currency": "USD",
"amount": 2500
}
}Additive format - cross-currency FX:
{
"debitAmount": {
"currency": "USD",
"amount": 2500
},
"creditAmount": {
"currency": "HKD"
}
}Provide
debitAmount(currency and amount) when you want the debit side to be authoritative.Provide only
creditAmount.currencyin that case; the bank assigns the exchange rate and final credited amount before forwarding to the beneficiary.If
debitAmountis omitted, the existingdebitCurrency+creditAmount(currency + amount) format applies with no change to current behaviour.debitCurrencyis not deprecated and remains fully supported.Both payload formats are accepted and return a successful response.
- The virtualAccountId in the route parameter identifies the source virtual account
- The request body specifies the destination external beneficiary account via
creditorAccount.identification - Ensure the virtual account has sufficient funds before making the request
- Virtual accounts must be in an active state to process withdrawals
- External transfers require additional beneficiary information for compliance
Virtual account withdrawals transfer funds from virtual accounts to external beneficiary accounts:
Virtual Account → External Beneficiary AccountWhen processing an external withdrawal transfer, funds flow from the virtual account to the external beneficiary account.
External transfers require additional information for regulatory compliance:
- debitCurrency: Currency to debit from the virtual account (e.g., "USD")
- creditAmount: Amount and currency to credit externally (e.g., { amount: "2500.00", currency: "USD" })
- debtor: Ordering customer information as
{ name, additionalInformation[] }(V2: structured object; V1 uses a plain string) - debtor.additionalInformation: Up to 3 lines, each max 35 characters
- debtorAgent: Ordering bank/agent identifier (free text, max 35 characters) - Optional
- creditorAccount.identification: External beneficiary account identifier (required, max 35 characters)
- creditorAccount.name / additionalInformation: Beneficiary name and auxiliary details (optional)
- chargesType: Who bears charges (e.g., OUR, BEN, SHA)
- creditorAgent: Beneficiary bank info (identification, name, additionalInformation)
- intermediaryAgent (optional): Intermediary bank info (identification, name, additionalInformation)
- remittanceInformation (optional): Unstructured remittance lines
- If
creditorAgent.identification(BIC/bank identifier) is provided,creditorAgent.nameandcreditorAgent.additionalInformationare optional and may be omitted. - If
creditorAgent.identificationis not provided, supplycreditorAgent.nameandcreditorAgent.additionalInformationto identify the beneficiary bank.
The API supports idempotency through the optional Idempotency-Key header:
- If no idempotency key is provided, the request is processed normally (duplicates are possible)
- If a valid UUID idempotency key is provided for a new transaction, the system stores the key and associates it with the transaction results
- If the same idempotency key is received again for the same endpoint/action, the system returns the previously stored response
- Idempotency keys are user-specific - different users with the same keys don't share cached responses
- The idempotency key must be a valid UUID format (e.g., "123e4567-e89b-12d3-a456-426614174000").
Clients must use the HTTP Accept header to indicate the desired response format:
- Set
Accept: application/jsonfor JSON responses (default) - Set
Accept: text/csvfor CSV responses If the Accept header is omitted,application/jsonis assumed.
All API requests use the versioned base URL:
https://api.bcb.bm/v2/virtual-accounts/{virtualAccountId}/withdrawals/external
async function processExternalWithdrawalV2() {
try {
const virtualAccountId = "1000320575";
const response = await fetch(`https://api.bcb.bm/v2/virtual-accounts/${virtualAccountId}/withdrawals/external`, {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json',
'Accept': 'application/json',
'Idempotency-Key': '123e4567-e89b-12d3-a456-426614174000' // Optional
},
body: JSON.stringify({
debitAmount: {
currency: "USD",
amount: "2500.00"
},
creditAmount: {
currency: "HKD"
},
debtor: {
name: "John Smith Corporation",
additionalInformation: [
"123 Business Street",
"London, UK SW1A 1AA"
]
},
debtorAgent: "CHASUS33XXX",
creditorAccount: {
identification: "GB29NWBK60161331926819",
name: "Acme Manufacturing Ltd",
additionalInformation: [
"123 Business Street",
"London, UK SW1A 1AA"
]
},
chargesType: "OUR",
creditorAgent: {
identification: "NWBKGB2L",
name: "NatWest Bank",
additionalInformation: [
"250 Bishopsgate",
"London, UK EC2M 4AA"
]
},
intermediaryAgent: {
identification: "CHASUS33",
name: "JPMorgan Chase Bank",
additionalInformation: [
"383 Madison Avenue",
"New York, NY 10017"
]
},
remittanceInformation: [
"Withdrawal from Virtual Account VA-2024-001",
"Transfer to external beneficiary account",
"Reference: WD-2024-789456"
]
})
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(`External withdrawal transfer failed: ${JSON.stringify(errorData)}`);
}
const data = await response.json();
console.log('External withdrawal transfer result:', data);
// Example processing of the returned object
const { id, status, uniqueIdentifier, details, linkedActivities } = data;
const { debitAmount, valueDate, childTransactionId, creditAmountCurrency, debitAccountNumber, creditAccountNumber } = details;
// Log the main transfer details
console.log('Transaction ID:', id);
console.log('Status:', status);
console.log('Unique Identifier:', uniqueIdentifier);
console.log('Debit Amount:', debitAmount.amount, debitAmount.currency);
console.log('Value Date:', valueDate);
console.log('Child Transaction ID:', childTransactionId);
console.log('Credit Amount Currency:', creditAmountCurrency);
// Process debit account information (virtual account)
console.log('Debit Account Number:', debitAccountNumber.number);
// Process credit account information (external beneficiary account)
console.log('Credit Account Number:', creditAccountNumber.number);
// Process linked activities
linkedActivities.forEach(activity => {
console.log('Linked Activity ID:', activity.id);
console.log('Linked Activity Transaction Status:', activity.transactionStatus);
console.log('Linked Activity Status:', activity.status);
console.log('Linked Activity Unique Identifier:', activity.uniqueIdentifier);
const { arrangementId, activityId, productId, currencyId, effectiveDate } = activity.activityDetails;
console.log('Linked Activity Arrangement ID:', arrangementId);
console.log('Linked Activity Activity ID:', activityId);
console.log('Linked Activity Product ID:', productId);
console.log('Linked Activity Currency ID:', currencyId);
console.log('Linked Activity Effective Date:', effectiveDate);
});
// Final status logging
if (status === 'success') {
console.log('The external withdrawal was successful.');
} else {
console.log('The external withdrawal failed:', status);
}
} catch (error) {
console.error('Error processing external withdrawal:', error);
}
}
// Example usage:
processExternalWithdrawalV2();Required Permission: withdraw-virtual-account
This endpoint requires the permission claim withdraw-virtual-account to be present in the JWT token. These permissions are embedded in the token during the authentication process and cannot be modified afterward. The token must be obtained with the appropriate permissions to access this endpoint.
The virtual account number from which funds will be withdrawn.
Payload containing external withdrawal transfer details. V2 uses a structured debtor object ({ name, additionalInformation[] }) instead of a plain string. For FX cross-currency, optional debitAmount (with creditAmount currency only) may be sent.
The currency code for the debit amount (e.g., "USD", "EUR"). Exactly 3 letters (ISO 4217).
The account number to which funds will be credited (destination account). Max length: 36 characters.
The ordering customer information or reference Max length: 35 characters.
Name by which the party is known and which is usually used to identify the party.
The ordering customer agent (e.g., bank identifier code). Max length: 35 characters.
Unambiguous identification of the account of the creditor to which a credit entry will be posted as a result of the payment transaction.
Specifies which party/parties will bear the charges associated with the processing of the transaction, e.g. 'OUR' Max length: 3 characters.
Remittance Information. Limit: up to 4 lines; each line max 35 characters.
- Mock serverhttps://developers.bcb.bm/_mock/apis/open-banking-api/open-banking-api/v2/virtual-accounts/{virtualAccountId}/withdrawals/external
- UAT Environment - Used for testing and integration purposeshttps://api-uat.bcb.bm/v2/virtual-accounts/{virtualAccountId}/withdrawals/external
- Production Environment - Live environment for production usehttps://api.bcb.bm/v2/virtual-accounts/{virtualAccountId}/withdrawals/external
- curl
- JavaScript
- Node.js
- Python
- Java
- C#
- PHP
- Go
- Ruby
- R
- Payload
curl -i -X POST \
'https://developers.bcb.bm/_mock/apis/open-banking-api/open-banking-api/v2/virtual-accounts/[object Object]/withdrawals/external' \
-H 'Authorization: Bearer <YOUR_jwt_HERE>' \
-H 'Content-Type: application/json' \
-d '{
"debitAmount": {
"currency": "USD",
"amount": 2500
},
"creditAmount": {
"currency": "HKD"
},
"debtor": {
"name": "John Smith Corporation",
"additionalInformation": [
"123 Business Street",
"London, UK SW1A 1AA"
]
},
"debtorAgent": "CHASUS33XXX",
"creditorAccount": {
"identification": "GB29NWBK60161331926819",
"name": "Acme Manufacturing Ltd",
"additionalInformation": [
"123 Business Street",
"London, UK SW1A 1AA"
]
},
"chargesType": "OUR",
"creditorAgent": {
"identification": "NWBKGB2L",
"name": "NatWest Bank",
"additionalInformation": [
"250 Bishopsgate",
"London, UK EC2M 4AA"
]
},
"intermediaryAgent": {
"identification": "CHASUS33",
"name": "JPMorgan Chase Bank",
"additionalInformation": [
"383 Madison Avenue",
"New York, NY 10017"
]
},
"remittanceInformation": [
"Withdrawal from Virtual Account VA-2024-001",
"Transfer to external beneficiary account",
"Reference: WD-2024-789456"
]
}'The withdrawal transfer was processed successfully.
The current processing status of the transaction, e.g. Completed, Pending, Failed
List of related financial activities
The current processing status of the transaction.
A unique identifier specific to this instance of the activity.
Unique identifier for the arrangement associated with this activity.
Identifier for the type of activity.
Product identifier related to the activity.
{ "id": "FT252324K67K", "status": "success", "uniqueIdentifier": "IRFX252332872527361.00", "details": { "creditAmount": { … }, "debitAmountCurrency": "USD", "debitAccountNumber": { … }, "creditAccountNumber": { … }, "valueDate": "2025-08-20T07:36:00.0000000Z" }, "linkedActivities": [] }