Changelog
Below is a log of changes to the Connect Financial API. Updates that affect only products or features in beta or limited release may not be reflected.
Each change can be described as either a breaking change or an ongoing change.
Ongoing changes: Ongoing changes are backwards-compatible and are added on an ongoing basis. These updates improve functionality without requiring changes to your existing integration.
Breaking changes: When we make backwards-incompatible changes, these are marked in the changelog with the 💥 symbol. Breaking changes may require you to update your integration to continue working properly.
Prior to the production release of breaking changes, we do two things:
- We release documentation for breaking changes in advance to give customers time to adopt the new changes.
- We make breaking changes available on our sandbox environment first. This allows you to explore the new changes and simplifies development.
Change Key
🌱 New feature
🍃 Improvement
🔧 Fix
💥 Breaking change
🔒 Security-related
Changelog
March 16th, 2026
🌱 Added KYB (Know Your Business) compliance system with full lifecycle support. New endpoints include:
GET /compliance/business/status/:customerId— Get business compliance status with actionable checks and next steps.POST /compliance/business/start-kyb— Start the KYB verification process for a business customer.POST /compliance/business/onboardings/:id/documents— Upload business compliance documents.POST /compliance/business/onboardings/:id/source-of-funds— Generate a business source of funds declaration PDF.
🌱 Added person relation management for business customers. These endpoints support both pre-approval (onboarding) and post-approval (beneficial owner) states:
POST /customers/business/:businessUserId/related-persons— Add a person relation (shareholder, representative).GET /customers/business/:businessUserId/related-persons— List person relations.PATCH /customers/business/:businessUserId/related-persons— Update a person relation.DELETE /customers/business/:businessUserId/related-persons— Remove a person relation.
🔒 Added nested DTO validation for person relation endpoints to ensure all input fields are properly validated.
March 11th, 2026
🌱 Added GET /customers/membership-programs endpoint. B2B clients can now list the available user membership programs for their client tier, including the UUID and display name for each program.
🌱 Added optional membershipProgram parameter to POST /customers/individual. B2B clients can now specify which user membership tier to assign during customer creation by providing either the membership tier UUID or display name. If omitted, the default membership for the client is used.
🌱 Added membership update support to PATCH /customers/:id. B2B clients can now change a customer's user membership tier by passing membershipProgram in the update payload.
March 4th, 2026
🍃 POST /cards/debit — The walletId field is now optional. If omitted, the customer's primary wallet is used. A virtual account (Zenus account) is no longer required on the wallet at card creation time.
July 3rd, 2025
🌱 Added an endpoint for retrieving balance for a wallet, under GET wallets/:id/balance. For more information, see Get Wallet Balance.
🌱 Added an endpoint for retrieving transactions under /baas/transactions, which allows for filtering by user, wallet and portfolio ID - as well as other commonly used filters.
🌱 Added a set of endpoints for configuring webhook subscriptions. These allow you to add, retrieve and update webhook subscriptions. We will add more functionality to these over time. For more information, see Webhooks.
🍃 Added multiple QOL improvements across existing endpoints. These include improved response payloads, more descriptive HTTP error codes, as well as improved API docs.
🍃 Improved error message when attempting to create a customer with a duplicate email address.
🔧 Fixed issue where API requests triggered through the documentation interface were failing while working correctly when called externally.
August 11th, 2025
🔧 Minor fixes regarding list customer endpoint filters.
🍃 Improving dtos for wallet and card endpoints.
🍃 Configuring withdrawal endpoint to work with USD_TEST on sandbox.
🍃 Including LOCAL_US_WIRE withdrawal option.
September 24th, 2025
🍃 Removed "Other" as option for individual customer enum.
🍃 Simplified inputs for the POST baas/transactions/withdrawal endpoint and improved its documentation.
🍃 Reduced the granularity of the individual customer occupation enum, accounting for just its macro categories (2 digits) instead of occupation (6 digits)
October 22nd, 2025
💥 Included a "v1" versioning prefix for endpoints
🌱 Added the KYC endpoints, for managing some required validations for the customer's onboarding. For more information see Compliance or contact us.
🌱 Added the digital asset endpoints, for managing digital asset addresses and withdrawals. For more information see Digital Assets
November 13th, 2025
🍃 Simplified inputs for the POST v1/digital/withdrawal endpoint and improved its documentation.
🍃 Included "createdAt" property on transaction detail and listing endpoints: GET /v1/baas/transactions/:id and GET /v1/baas/transactions
🍃 Occupation Field Made Optional for endpoints POST v1/customers and PATCH v1/customers/:customerId
🌱 Added the trade endpoints: GET /v1/trades/asset-pairs to list possible trades, POST /v1/trades/quotes to generate a executable trade and POST /v1/trades/quotes/:quoteId/execute to execute the quote, for more information see Trades
🔧 Fixed a bug related to address updating that was preventing KYC's from being initialized
November 14th, 2025
🌱 Added new webhook event types for cooperative authorization card transactions:
COOP_AUTH_0100- Authorization requests (ISO8583 MTI 0100)COOP_AUTH_0120- Advice requests (ISO8583 MTI 0120)COOP_AUTH_0200- Financial transactions (ISO8583 MTI 0200)COOP_AUTH_0220- Authorization completions (ISO8583 MTI 0220)COOP_AUTH_0420- Reversal transactions (ISO8583 MTI 0420)
These events are automatically emitted for cards configured with cardTransactionHandler = 'COOP_AUTH'. Clients can subscribe to these events using the existing webhook subscription API. See Webhooks for more information.
Note: Initial implementation includes basic event payloads. Future updates will include complete ISO8583 field mapping as specified in the cooperative authorization specification.
November 19th, 2025
🌱 Added an endpoint for generating JWT tokens for Vault SDK integration, under POST /v1/vault/token. For more information, see Vault SDK.
December 3rd, 2025
🌱 Added an endpoint for retrieving VGS SDK configuration, under GET /v1/vault/config. This endpoint returns the vault ID, environment, CNAME, and route ID needed to initialize the Secure Connect SDK. For more information, see Vault SDK.
December 6th, 2025
🌱 Added bank lookup validation endpoints for validating routing numbers, SWIFT codes, and IBANs:
GET /v1/payments/validate/routing/:routingNumber- Validate a US ABA routing number and retrieve bank informationGET /v1/payments/validate/swift/:swiftCode- Validate a SWIFT/BIC code and retrieve bank informationGET /v1/payments/validate/iban/:iban- Validate an IBAN and retrieve bank/country information
🍃 Enhanced withdrawal endpoint (POST /v1/baas/transactions/withdrawal) with automatic bank validation:
- Routing numbers are now validated for ACH and US_WIRE payments
- SWIFT codes are validated when account number type is SWIFT
- IBANs are validated when account number type is IBAN
- Bank name and address are auto-populated from validation results if not provided
🍃 Enhanced counterparty endpoints with automatic bank validation:
POST /v1/customers/:customerId/portfolios/:portfolioId/counterpartiesnow validates bank identifiersPATCH /v1/customers/:customerId/portfolios/:portfolioId/counterparties/:counterpartyIdnow validates bank identifiers- Validated bank information (bankName, bankCity, bankState, bankCountry) is stored with counterparty records
- Counterparty response DTOs now include bank validation information
December 8th, 2025
💥 Breaking Change: Simplified withdrawal endpoint DTO structure (POST /v1/baas/transactions/withdrawal)
The withdrawal endpoint has been updated to use a flat DTO structure, replacing the previous nested destination object. This change aligns the B2B gateway-api with the mobile-gateway-api pattern for consistency.
Key Changes:
| Old Field (Nested) | New Field (Flat) | Notes |
|---|---|---|
destination.name | name | Beneficiary name moved to root level |
destination.accountNumber.value | accountNumber | Flattened, type assumed to be BBAN |
destination.accountNumber.type | (removed) | Always BBAN |
destination.financialInstitutionId | routingNumber | For ACH/US_WIRE domestic transfers |
| (new) | bicSwiftCode | For SWIFT/US_WIRE international transfers |
destination.personTypeCode | personTypeCode | Uses Zenus enum (P for Private, L for Legal) |
destination.address.street1 | street1 | Address fields moved to root level |
destination.address.street2 | street2 | Optional |
destination.address.cityCounty | cityCounty | |
destination.address.stateRegion | stateRegion | |
destination.address.zip | zip | |
destination.address.countryCode | countryCode | |
destination.partyIdentification.identificationTypeCode | identificationTypeCode | Optional |
destination.partyIdentification.identificationValue | identificationValue | Optional |
preferredPaymentScheme | transferNetwork | Renamed; see new enum values below |
details | (removed) | No longer required |
💥 Breaking Change: Updated transferNetwork enum values
The transferNetwork field now uses more specific values to distinguish between domestic and cross-border transfers:
| Old Value | New Value(s) | Description |
|---|---|---|
ACH | ACH_DOMESTIC | US domestic ACH transfer |
ACH | ACH_CROSSBORDER | International ACH Transfer (IAT) |
US_WIRE | FEDWIRE_DOMESTIC | Domestic Fedwire transfer using routing number |
US_WIRE | FEDWIRE_CROSSBORDER | Cross-border Fedwire transfer using SWIFT code |
SWIFT | SWIFT | International SWIFT transfer (unchanged) |
Routing/SWIFT Code Requirements:
- ACH_DOMESTIC:
routingNumberis required,bicSwiftCodeis not allowed - ACH_CROSSBORDER:
routingNumberis required,bicSwiftCodeis not allowed - FEDWIRE_DOMESTIC:
routingNumberis required,bicSwiftCodeis not allowed - FEDWIRE_CROSSBORDER:
bicSwiftCodeis required,routingNumberis not allowed - SWIFT:
bicSwiftCodeis required,routingNumberis not allowed
🍃 Enhancement: bankName and bankAddress are now optional
Both bankName and bankAddress fields are now optional. If not provided, they will be automatically populated from routing number or SWIFT code validation:
- For routing number validation: Bank name and address retrieved from Federal Reserve Bank database
- For SWIFT code validation: Bank name and address retrieved from SWIFT directory
This allows clients to omit these fields and rely on our validated bank data for accuracy.
Migration Example:
Old format:
{
"walletId": "wallet_123",
"amount": "100.00",
"details": "Payment for services",
"preferredPaymentScheme": "LOCAL_US_ACH",
"destination": {
"name": "John Doe",
"accountNumber": { "value": "123456789", "type": "BBAN" },
"financialInstitutionId": "021000021",
"personTypeCode": "PRIVATE",
"address": {
"street1": "123 Main St",
"cityCounty": "New York",
"stateRegion": "NY",
"zip": "10001",
"countryCode": "US"
}
}
}
New format (with optional bankName/bankAddress omitted - will be auto-populated):
{
"walletId": "wallet_123",
"amount": "100.00",
"name": "John Doe",
"transferNetwork": "ACH_DOMESTIC",
"personTypeCode": "P",
"routingNumber": "021000021",
"accountNumber": "123456789",
"street1": "123 Main St",
"cityCounty": "New York",
"stateRegion": "NY",
"countryCode": "US",
"zip": "10001"
}
New format (with bankName/bankAddress provided - will use provided values):
{
"walletId": "wallet_123",
"amount": "100.00",
"bankName": "Chase Bank",
"bankAddress": "270 Park Ave, New York, NY 10017",
"name": "John Doe",
"transferNetwork": "ACH_DOMESTIC",
"personTypeCode": "P",
"routingNumber": "021000021",
"accountNumber": "123456789",
"street1": "123 Main St",
"cityCounty": "New York",
"stateRegion": "NY",
"countryCode": "US",
"zip": "10001"
}
Note on personTypeCode values:
P= Private (Individual)L= Legal (Business)
💥 Breaking Change: Updated counterparty endpoints to use standardized transferNetwork enum
The counterparty endpoints now use the same BankPaymentSchemeEnum values as the withdrawal endpoint for consistency across all payment-related APIs.
Affected Endpoints:
POST /v1/customers/:customerId/portfolios/:portfolioId/counterparties- Create counterpartyPATCH /v1/customers/:customerId/portfolios/:portfolioId/counterparties/:counterpartyId- Update counterparty
Key Changes:
| Old Field | New Field | Notes |
|---|---|---|
financialInstitutionId | routingNumber | Renamed for clarity |
| (none) | transferNetwork | New required field - specifies payment network type |
| (none) | bicSwiftCode | New field for SWIFT transfers |
| (none) | accountHolderName | New required field for create operations |
accountNumberType | (removed) | No longer required - Zenus treats all account numbers as BBAN |
transferNetwork Enum Values:
ACH_DOMESTIC- US domestic ACH transferACH_CROSSBORDER- International ACH Transfer (IAT)FEDWIRE_DOMESTIC- Domestic Fedwire transferFEDWIRE_CROSSBORDER- Cross-border Fedwire transferSWIFT- International SWIFT transfer
Validation Rules by Transfer Network:
- ACH_DOMESTIC / ACH_CROSSBORDER:
routingNumberrequired - FEDWIRE_DOMESTIC:
routingNumberrequired - FEDWIRE_CROSSBORDER / SWIFT:
bicSwiftCoderequired
Create Counterparty Example:
Old format:
{
"name": "John Doe",
"financialInstitutionId": "063107513",
"accountNumberType": "BBAN",
"accountNumberValue": "123456789",
"countryCode": "US",
"street1": "123 Main St",
"cityCounty": "Miami",
"stateRegion": "FL",
"zip": "33101"
}
New format:
{
"transferNetwork": "ACH_DOMESTIC",
"name": "John Doe",
"accountHolderName": "John Doe",
"routingNumber": "063107513",
"accountNumberValue": "123456789",
"countryCode": "US",
"street1": "123 Main St",
"cityCounty": "Miami",
"stateRegion": "FL",
"zip": "33101"
}
SWIFT Counterparty Example:
{
"transferNetwork": "SWIFT",
"name": "Jane Smith",
"accountHolderName": "Jane Smith",
"bicSwiftCode": "BOFAUS33XXX",
"accountNumberValue": "GB82WEST12345698765432",
"countryCode": "GB",
"street1": "10 Downing Street",
"cityCounty": "London",
"zip": "SW1A 2AA"
}
Response DTO Enhancements:
Counterparty responses now include additional fields for better visibility:
transferNetwork- The payment network typeroutingNumber- ABA routing number (if applicable)bicSwiftCode- SWIFT/BIC code (if applicable)bankName- Validated bank namebankCity- Bank city from validationbankState- Bank state from validationbankCountry- Bank country from validation
December 19th, 2025
🌱 Added an endpoint for assigning dedicated account numbers to wallets, under POST /v1/virtual-accounts/assign-dedicated-account-number. This endpoint assigns a dedicated account number to a wallet that already has a virtual account. Dedicated account numbers are used for identifying incoming deposits.
💥 Breaking Change: Updated SWIFT banking details response structure (GET /v1/virtual-accounts/banking-details/:walletId)
The SWIFT banking details endpoint has been updated to return a richer, nested response structure with beneficiary address and intermediary bank information.
Key Changes:
| Old Field | New Field | Notes |
|---|---|---|
swift | beneficiary_bank.swift | Moved into beneficiary_bank object |
account_number | beneficiary.account_number | Moved into beneficiary object |
bank_address | beneficiary_bank.bank_address | Moved into beneficiary_bank object |
beneficiary | beneficiary.name | Renamed and moved into beneficiary object |
| (new) | beneficiary.address | New field - beneficiary's physical address |
| (new) | beneficiary_bank.name | New field - bank name |
| (new) | intermediary_bank | New object - intermediary bank details |
| (new) | intermediary_bank.name | New field - intermediary bank name |
| (new) | intermediary_bank.routing_number | New field - intermediary bank routing number |
| (new) | intermediary_bank.bic_code | New field - intermediary bank BIC code |
Migration Example:
Old format:
{
"swift": "ZEITPRSJXXX",
"account_number": "256783259046169",
"bank_address": "CITI TOWER, 252 AVE PONCE DE LEON, FLOOR 19, SAN JUAN, SAN JUAN, 00918",
"beneficiary": "John Doe"
}
New format:
{
"beneficiary": {
"name": "John Doe",
"address": "123 Main St, San Juan, PR, 00918, US",
"account_number": "256783259046169"
},
"beneficiary_bank": {
"name": "Zenus Bank International Inc",
"swift": "ZEITPRSJXXX",
"bank_address": "Zenus Tower, 19th Floor, 252 Ponce de Leon, San Juan, PR, 00918"
},
"intermediary_bank": {
"name": "JP Morgan Chase NA, New York, NY",
"routing_number": "021000021",
"bic_code": "CHASUS33"
}
}
Note: The new response structure provides complete SWIFT transfer instructions including intermediary bank details, which are required for international wire transfers to Zenus Bank accounts.
January 6th, 2026
🍃 Enhancement: ACH and FedWire banking details account_number field is now optional
The GET /v1/virtual-accounts/banking-details/:walletId endpoint has been updated to make the account_number field optional in the response for ACH and FedWire transfer types.
Behavior:
| Transfer Type | account_number Field |
|---|---|
| ACH | Returns the dedicated account number if assigned, otherwise the field is omitted |
| FEDWIRE (with dedicated account number) | Returns the dedicated account number |
| FEDWIRE (without dedicated account number) | Returns master account with reference field (unchanged) |
| SWIFT | No change |
Response Example (ACH - No dedicated account number assigned):
{
"message": "ACH details retrieved with success.",
"data": {
"beneficiary": {
"name": "John Doe",
"address": "123 Main St, San Juan, PR, 00918, US"
},
"beneficiary_bank": {
"name": "Zenus Bank International Inc",
"routing_number": "021583805",
"bank_address": "Zenus Tower, 19th Floor, 252 Ponce de Leon, San Juan, PR, 00918"
}
}
}
Response Example (ACH - Dedicated account number assigned):
{
"message": "ACH details retrieved with success.",
"data": {
"beneficiary": {
"name": "John Doe",
"address": "123 Main St, San Juan, PR, 00918, US",
"account_number": "9876543210"
},
"beneficiary_bank": {
"name": "Zenus Bank International Inc",
"routing_number": "021583805",
"bank_address": "Zenus Tower, 19th Floor, 252 Ponce de Leon, San Juan, PR, 00918"
}
}
}
Client Impact: Clients should check for the presence of the account_number field before displaying ACH/FedWire deposit instructions to end users. To assign a dedicated account number, use the POST /v1/virtual-accounts/assign-dedicated-account-number endpoint.
January 7th, 2026
🌱 New Endpoint: Re-run KYC Process (POST /v1/compliance/kyc/:onboardingId/rerun)
Clients can now programmatically restart a customer's KYC process when:
- Customer entered incorrect information
- Documents expired or were rejected
- Customer needs to update their data
Key Features:
- Archives the previous onboarding (preserves audit trail)
- Creates a fresh KYC application with updated customer data
- Returns new SDK links and QR codes for document/biometric capture
- Only allowed for customers in
PENDINGorPROCESSINGstatus
Response:
{
"message": "KYC process restarted successfully",
"data": {
"onboardingId": "new-onboarding-uuid",
"sdk": {
"link": "https://alloy.co/sdk/...",
"qrCode": "data:image/png;base64,..."
}
}
}
For more information, see Re-run KYC Process.
🌱 New Endpoint: Get Compliance Status (GET /v1/compliance/status/:customerId)
Retrieve a comprehensive breakdown of a customer's compliance status, including exactly what requirements are met or missing before they can create a virtual account.
Response includes:
isCompliant- Overall compliance statusonboardingStatus- Current KYC status (PENDING, PROCESSING, APPROVED, etc.)verificationStatus- SDK identity verification statusnextAction- Primary action to takechecks[]- Array of compliance checks withsuggestedActionfor failed itemssummary- Counts and list of failed required checks
Compliance Check Types:
| Check | Description |
|---|---|
KYC_DATA_PRESENT | KYC data has been submitted |
KYC_NOT_DENIED | Application not denied |
KYC_STARTED | KYC process has been initiated |
KYC_APPROVED | Application approved by Alloy |
REGISTRATION_ADDRESS | Registration address on file |
TAX_COUNTRY | Tax country specified |
DOC_SOURCE_OF_FUNDS | Source of funds document uploaded |
DOC_FATCA | W9/W8BEN document uploaded |
DOC_BIOMETRIC_REPORT | Biometric verification report available |
DOC_PROOF_OF_ADDRESS | Proof of address document uploaded |
| Note: Response structure updated in January 13th, 2026. See breaking change entry below for full details. |
For more information, see Get Compliance Status.
🌱 New Webhook Events for KYC lifecycle:
| Event | Description |
|---|---|
CUSTOMER_KYC_RESTARTED | Emitted when KYC is re-run via the new endpoint |
CUSTOMER_KYC_SDK_EXPIRED | Emitted when SDK links expire before customer completes upload |
CUSTOMER_KYC_ERROR | Emitted when the verification provider encounters a processing error |
Subscribe to these events using the Webhook API to receive real-time KYC status updates.
🍃 Enhancement: Customer responses now include onboardingId
The following endpoints now return the customer's most recent onboarding ID:
GET /v1/customers/:idGET /v1/customers
Example Response:
{
"id": "customer-uuid",
"type": "PRIVATE",
"onboardingId": "onboarding-uuid",
"portfolios": [...]
}
This allows clients to track KYC status without making additional API calls.
🍃 Enhancement: Customer data can be updated during KYC process
The PATCH /v1/customers/:id endpoint now allows updating KYC-related data (name, birth date, documents, address) even after KYC has been initiated. Previously, this was blocked once the process started.
Supported statuses for updates:
PENDING- KYC not yet startedPROCESSING- KYC in progress (NEW)
This enables the re-run flow: update customer data first, then re-run KYC to submit the corrected information.
January 8th, 2026
🍃 Enhanced card creation with program-level transaction handler inheritance
Cards now automatically inherit the transaction handler from the program they are created for. This simplifies the API for coop clients:
Key Changes:
- Cards now inherit transaction handling behavior from their program
For Coop Clients:
Use the designated coop card program IDs provided by us. Cards created from these programs will automatically route authorization requests to your WebSocket client without needing to specify cardTransactionHandler in each API request.
January 15th, 2026
🌱 Major Update: Unified Transaction System
We've completely unified how transactions are structured across all domains (cards, bank transfers, crypto). This update introduces a consistent parent-child architecture that makes it easier to track, correlate, and display transaction data.
What's New:
-
Parent-Child Transaction Architecture - Every transaction lifecycle now follows a parent-child model where:
- Parent records are immutable containers that group related events
- Child records represent individual events with all details (type, status, amount, operation)
-
New Unified Wallet Transactions Endpoint -
GET /v1/transactions?walletId=Xprovides a view of all wallet transactions
New Endpoints:
| Endpoint | Description |
|---|---|
GET /v1/transactions?walletId=X | Unified wallet transactions |
GET /v1/transactions/:id | Get wallet transaction details |
GET /v1/cards/transactions?cardId=X | Card transactions with grouping |
GET /v1/cards/transactions/:id | Card transaction details |
GET /v1/baas/transactions?walletId=X | Bank transactions with grouping |
GET /v1/baas/transactions/:id | Bank transaction details |
How to Use:
- Unified wallet history →
GET /v1/transactions?walletId=X - Filter by domain parent →
GET /v1/transactions?walletId=X&parentCardTransactionId=Y(get all wallet transactions from one card swipe) - Domain-specific with grouping →
GET /v1/baas/transactions?walletId=XorGET /v1/cards/transactions?cardId=X
See the Transactions' Lifecycle Guide for complete examples and step-by-step flows.
💥 Breaking Change: Bank & Crypto Webhook Event Names Renamed
The following webhook event names have been updated to follow a consistent naming convention:
| Old Event Name | New Event Name | Payload |
|---|---|---|
DEPOSIT_TRANSACTION_INITIALIZED | BANK_DEPOSIT_TRANSACTION_PENDING | { walletId, bankTransactionId } |
DEPOSIT_TRANSACTION_SUCCEEDED | BANK_DEPOSIT_TRANSACTION_COMPLETED | { walletId, bankTransactionId } |
DEPOSIT_TRANSACTION_FAILED | BANK_DEPOSIT_TRANSACTION_FAILED | { walletId, bankTransactionId } |
WITHDRAW_TRANSACTION_INITIALIZED | BANK_WITHDRAWAL_TRANSACTION_PENDING | { walletId, bankTransactionId } |
WITHDRAW_TRANSACTION_SUCCEEDED | BANK_WITHDRAWAL_TRANSACTION_COMPLETED | { walletId, bankTransactionId } |
WITHDRAW_TRANSACTION_FAILED | BANK_WITHDRAWAL_TRANSACTION_FAILED | { walletId, bankTransactionId } |
VIRTUAL_INTERNAL_TRANSACTION_SUCCEEDED | INTERNAL_TRANSACTION_COMPLETED | { walletId, transactionId } |
Important Change for Internal Transfers:
- Internal transfers now send 2 webhooks - one to each wallet owner (source and destination)
- Each webhook contains the child transaction ID that affects that specific wallet
- Source wallet owner receives webhook with debit transaction ID
- Destination wallet owner receives webhook with credit transaction ID
💥 Breaking Change: GET /v1/customers/:id/transactions Endpoint Removed
Migration:
Use the new wallet transactions endpoint GET /v1/transactions with the walletId query parameter:
# Old (removed)
GET /v1/customers/:id/transactions
# New (use this instead)
GET /v1/transactions?walletId={walletId}
The /v1/transactions endpoint returns a simplified view of all wallet transactions.
🌱 New: Crypto Transaction Webhook Events
Subscribe to these new events to receive notifications for crypto deposits and withdrawals:
| Event | When it fires | Payload |
|---|---|---|
CRYPTO_DEPOSIT_TRANSACTION_PENDING | Crypto deposit detected on-chain | { walletId, cryptoTransactionId } |
CRYPTO_DEPOSIT_TRANSACTION_COMPLETED | Crypto deposit confirmed | { walletId, cryptoTransactionId } |
CRYPTO_DEPOSIT_TRANSACTION_FAILED | Crypto deposit failed | { walletId, cryptoTransactionId } |
CRYPTO_WITHDRAWAL_TRANSACTION_PENDING | Crypto withdrawal initiated | { walletId, cryptoTransactionId } |
CRYPTO_WITHDRAWAL_TRANSACTION_COMPLETED | Crypto withdrawal confirmed | { walletId, cryptoTransactionId } |
CRYPTO_WITHDRAWAL_TRANSACTION_FAILED | Crypto withdrawal failed | { walletId, cryptoTransactionId } |
🍃 Improvement: Card Transaction Webhook Payloads Simplified
Card transaction webhook payloads have been simplified to contain only essential IDs:
New minimal payload:
{
"eventType": "CARD_TRANSACTION_PENDING",
"data": {
"cardId": "80d63380-fd9b-46c0-80b7-dabd548b2be2",
"cardTransactionId": "a1b2c3d4-e5f6-7890-1234-567890abcdef"
}
}
🌱 New: Card Transactions Webhook Events
Clients can now receive instant webhook notifications whenever a card transaction occurs. Subscribe to these new event types via the webhook subscription API:
| Event | When it fires |
|---|---|
CARD_TRANSACTION_PENDING | Authorization approved — a hold is placed on the card |
CARD_TRANSACTION_COMPLETED | Transaction settled — funds have been captured |
CARD_TRANSACTION_FAILED | Authorization denied — no hold placed |
CARD_TRANSACTION_CANCELLED | Transaction reversed or voided |
Webhook payload:
{
"eventType": "CARD_TRANSACTION_PENDING",
"data": {
"cardId": "80d63380-fd9b-46c0-80b7-dabd548b2be2",
"transactionId": "a1b2c3d4-e5f6-7890-1234-567890abcdef"
}
}
Use the new card transaction endpoints (below) to retrieve full transaction details.
🌱 New: Card transaction API endpoints
Two new endpoints for retrieving card transaction data:
List transactions for a card:
GET /v1/cards/transactions?cardId={cardId}
Get transaction details:
GET /v1/cards/transactions/:id
These endpoints work for all card types (credit and debit) and complement the new webhook events. When you receive a webhook, use the cardTransactionId to fetch complete details.
💥 Breaking Change: Compliance Status Endpoint Refactored to better support client automations (GET /v1/compliance/status/:customerId)
The compliance status endpoint has been redesigned to enable client automation without message parsing.
New suggestedAction / nextAction Values:
| Action | What to do |
|---|---|
START_KYC | Initiate the KYC process |
COMPLETE_SDK_FLOW | User must complete identity verification SDK |
UPLOAD_DOCUMENT | Upload required compliance document |
UPDATE_PROFILE | Update customer profile data |
RERUN_KYC | Re-run KYC process (expired/needs correction) |
WAIT | No user action needed - system processing (e.g., SDK done, docs uploaded, awaiting approval) |
CONTACT_SUPPORT | Terminal failure, verification error, or denied - requires support |
Updated Check Types:
| Check | Description |
|---|---|
KYC_DATA_PRESENT | KYC data has been submitted |
KYC_STARTED | KYC process has been initiated |
SDK_VERIFICATION_COMPLETED | Identity verification SDK completed |
KYC_STATUS | Overall KYC status (passed = APPROVED) |
REGISTRATION_ADDRESS | Registration address on file |
TAX_COUNTRY | Tax country specified |
OCCUPATION | Occupation registered |
DOC_SOURCE_OF_FUNDS | Source of funds document uploaded |
DOC_FATCA | W9/W8BEN document uploaded |
DOC_BIOMETRIC_REPORT | Biometric verification report available |
DOC_PROOF_OF_ADDRESS | Proof of address document uploaded |
Here you will find a comprehensive guide explaining how to integrate the KYC compliance system using both webhooks (push) and the Compliance Status API (pull). This guide includes complete flow diagrams, and edge case handling.
🍃 Improvement: Removed deprecated currencyCode field from transaction DTOs
The currencyCode field has been deprecated and removed from transaction response DTOs across the following endpoints:
GET /v1/baas/transactionsGET /v1/baas/transactions/:idPOST /v1/baas/transactions/withdrawalPOST /v1/digital/withdrawal
The asset field (e.g., "USD") remains the standard way to identify the currency/asset for a transaction.
🍃 Improvement: walletId now optional for COOP Auth debit card creation
When creating a debit card with a COOP Auth-enabled card program, the walletId field is now optional. If omitted, a wallet will be auto-created for the card.
Behavior:
walletIdomitted + COOP Auth-enabled card program → wallet auto-createdwalletIdomitted + standard card program → error (wallet with Virtual Account still required)walletIdprovided → validates and uses existing wallet (unchanged behavior)
🍃 Enhanced coop-auth webhook payloads with networkDataRef field
All cooperative authorization webhook events (COOP_AUTH_0100, COOP_AUTH_0120, COOP_AUTH_0200, COOP_AUTH_0220, COOP_AUTH_0420) now include a new optional field:
| Field | Type | Description |
|---|---|---|
networkDataRef | string | undefined | Stable transaction lifecycle identifier extracted from network data |
Why this matters: When settlement batching occurs, the retrieval reference number (RRN) may change between authorization (0100) and completion (0220) messages. The networkDataRef field remains constant throughout the transaction lifecycle, enabling reliable correlation of related messages.
Usage:
- Use
networkDataRefas a fallback correlation key when RRN-based matching fails - This field is extracted from the network data (positions 9-24 of DE63)
- If network data is not present or the identifier cannot be extracted, the field will be
undefined
Example payload with new field:
{
"mti": "0220",
"rrn": "500000000002",
"stan": "300001",
"networkData": "0002 306012661247577 0 VISA ",
"networkDataRef": "306012661247577",
...
}
Backward Compatibility: This is an additive change. The new field is optional and will not affect existing integrations that do not use it.
🔧 Fix: Corrected currency conversion in COOP Auth webhook payloads
Fixed a bug in COOP Auth card webhook payloads where the currency field was incorrectly returning ISO 4217 numeric codes (e.g., "840") instead of human-readable acronyms (e.g., "USD"). Webhook payloads now correctly display the currency acronym.
January 17th, 2026
🌱 New: Delete webhook endpoint and WEBHOOK_DELETED notification
Added a new endpoint to delete webhook subscriptions and a corresponding notification event:
New Endpoint:
DELETE /v1/webhooks/:id
New Webhook Event:
| Event | When it fires | Payload |
|---|---|---|
WEBHOOK_DELETED | Webhook subscription is deleted | { webhookId } |
Subscribe to this event to track when webhook subscriptions are removed from your account.
🔧 Fixed compliance status endpoint (GET /v1/compliance/status/:customerId) incorrectly returning nextAction: COMPLETE_SDK_FLOW when KYC verification is under manual review. The endpoint now correctly returns nextAction: WAIT when the SDK verification is pending manual review. For more details on the manual review flow, see KYC Compliance Flow - Under Review.
January 20th, 2026
💥 Breaking Change: Consolidated address management for customers.
- The dedicated
POST /v1/customers/:id/addressesendpoint has been removed - Use
PATCH /v1/customers/:idto add or update billing/delivery addresses - The
POST /v1/customersendpoint now accepts optionalbillingAddressanddeliveryAddressfields at creation time
January 29th, 2026
🔧 Fixed an issue where the KYC onboardingStatus would remain PROCESSING instead of transitioning to APPROVED after completing SDK verification and uploading all required documents, resulting in an unexpected WAIT suggested nextAction.
🔧 Fixed an issue where the KYC onboardingStatus could incorrectly show PROCESSING when the verification was automatically denied. The status now correctly reflects the denial outcome.
February 5th, 2026
🍃 Enhancement: Wallet transactions endpoint now returns domain linking fields and supports filtering by them
The GET /v1/transactions endpoint now returns and supports filtering by: parentTransactionId, cardTransactionId, parentCardTransactionId, bankTransactionId, parentBankTransactionId, cryptoTransactionId, and parentCryptoTransactionId.
This enables clients to correlate wallet transactions with their originating domain and retrieve grouped transactions (e.g., all wallet entries from a single card swipe).
🔧 Fixed an issue where filtering wallet transactions by parentCardTransactionId returned no results.
🔧 Fixed an issue where card creation was failing in Sandbox.
🔧 Fixed an issue where Virtual Account creation was failing with an unexpected PROOF_OF_ADDRESS requirement for clients that supply IP address during customer creation.
🔧 Fixed an issue with the withdrawal endpoint (POST /v1/baas/transactions/withdrawal) where certain requests were failing unexpectedly.
February 6th, 2026
🔧 Fixed an issue where customers onboarded through External KYC clients were incorrectly marked as non-compliant. The SDK_VERIFICATION_COMPLETED check now correctly returns passed: true and required: false for External KYC customers, as they verify identity through their own KYC provider.
🔧 Fixed an issue where External KYC customers could not be automatically approved. The system now approves External KYC customers when all required documents are uploaded.
🌱 Added comprehensive documentation for External KYC Integration in the KYC Compliance Flow guide. This includes integration flow diagrams, required documents, example API responses, and webhook event differences.
🍃 The Compliance Status API (GET /v1/compliance/status/:customerId) now returns strategy-aware check requirements. The required field on each check accurately reflects whether that check applies to the customer's onboarding strategy.
February 20th, 2026
💥 Breaking Change: Removed derived name field from customer response
The name field has been removed from GET /v1/customers/:id and GET /v1/customers responses. This field was a server-derived composite of first/last name or email, and was not directly editable. Use kyc.firstName and kyc.lastName instead.
💥 Breaking Change: Removed bankName and bankAddress from the withdrawal endpoint
The bankName and bankAddress fields have been removed from POST /v1/baas/withdrawals. These fields are no longer required and should be omitted from requests.
🌱 New: Virtual Reference Numbers (VRNs) for ACH and FedWire deposits
Virtual accounts can now be assigned a dedicated Virtual Reference Number (VRN). A unique account reference number at our Correspondant Bank that ENABLES ACH deposits, and allows FEDWIRE to be routed directly to the customer's account without requiring a reference code in the transfer memo.
Use POST /v1/virtual-accounts/assign-vrn to assign a VRN. Once assigned, the ACH and FedWire banking details returned by GET /v1/virtual-accounts/banking-details/:walletId will automatically include the VRN in the deposit instructions.
🍃 Enhancement: Customer endpoints now return full profile and KYC data
GET /v1/customers/:id and GET /v1/customers now return the complete profile data that was previously only accepted on create/update. This means you can read back everything you submitted.
New fields in the customer response:
| Field | Description |
|---|---|
email | Email address |
phoneNumber | Phone number |
phoneCountryCode | Phone country code (e.g. "1" for US) |
kyc.firstName | First name |
kyc.middleName | Middle name |
kyc.lastName | Last name |
kyc.sex | Gender |
kyc.birthDate | Date of birth |
kyc.documentSsn | SSN (masked) |
kyc.documentIdCard | ID card number |
kyc.documentLicense | License number |
kyc.documentPassport | Passport number |
kyc.nationality | Country code |
kyc.taxIdCountry | Country that issued the SSN / tax ID document (ISO 3166-1 Alpha-2). May differ from nationality. |
kyc.occupation | Occupation code |
kyc.ipAddress | IP address |
kyc.mainAddress | Registration address (street1, street2, cityCounty, stateRegion, zip, countryCode) |
billingAddress | Billing address (street1, street2, cityCounty, stateRegion, zip, countryCode) |
deliveryAddress | Delivery address (street1, street2, cityCounty, stateRegion, zip, countryCode) |
Example Response:
{
"id": "customer-uuid",
"type": "PRIVATE",
"email": "john@example.com",
"phoneNumber": "5551234567",
"phoneCountryCode": "1",
"kyc": {
"firstName": "John",
"lastName": "Doe",
"birthDate": "1990-01-15",
"nationality": "GB",
"taxIdCountry": "US",
"occupation": "11",
"mainAddress": {
"street1": "123 Main St",
"cityCounty": "New York",
"stateRegion": "NY",
"zip": "10001",
"countryCode": "US"
}
},
"billingAddress": {
"street1": "123 Main St",
"cityCounty": "New York",
"stateRegion": "NY",
"zip": "10001",
"countryCode": "US"
},
"onboardingId": "onboarding-uuid",
"portfolios": [...]
}
🍃 Enhancement: New optional taxIdCountry field on customer create and update
POST /v1/customers/individual and PATCH /v1/customers/:id now accept an optional kyc.taxIdCountry field (ISO 3166-1 Alpha-2). This represents the country that issued the customer's SSN or tax identification document, which may differ from their nationality.
Existing integrations are unaffected.
🌱 Added a new "Handling UPDATE_PROFILE" section to the KYC Compliance Flow guide. This documents which failed compliance checks map to which PATCH /v1/customers/:id fields, with step-by-step instructions and a JSON example.
🍃 Enhancement: Bank transaction webhook payloads now include richer data
Bank deposit and withdrawal webhook events now include amount, asset, bankNetwork, and counterparty fields in their payloads. For full payload schemas, see Webhook Notifications.
Updated webhook payload:
{
"eventType": "BANK_DEPOSIT_TRANSACTION_COMPLETED",
"data": {
"walletId": "123e4567-e89b-12d3-a456-426614174000",
"bankTransactionId": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"amount": "1500.00",
"asset": "USD",
"bankNetwork": "ACH",
"counterparty": {
"name": "John Doe",
"givenName": "John",
"surname": "Doe",
"accountNumber": "123456789",
"swiftCode": null,
"routingNumber": "021000021",
"financialInstitutionId": null,
"street1": "123 Main St",
"street2": null,
"cityCounty": "New York",
"stateRegion": "NY",
"countryCode": "US",
"zip": "10001",
"addressLine": null
}
}
}
Notes:
counterpartycontains sender information for deposits and isnullfor withdrawalsbankNetworkis one of:ACH,FEDWIRE,SWIFT, ornullif unknownamountis the transaction amount as a stringassetis the currency acronym (e.g.,"USD")- Financial institution ID is returned as
swiftCode(for BIC/SWIFT),routingNumber(for ABA/routing), orfinancialInstitutionId(fallback)
Backward Compatibility: These are additive fields. Existing integrations that do not use these fields will not be affected.
🍃 Enhancement: Bank transaction API responses now include counterparty data
The following endpoints now return a counterparty object for bank transactions:
GET /v1/baas/transactions/:idGET /v1/baas/transactions?walletId=X
The counterparty field contains sender information for deposits and is null for withdrawals.
🔧 Fix: Corrected bankNetwork mapping for bank transactions
- Outgoing FedWire withdrawals now correctly report
FEDWIREinstead ofSWIFT - Added
FEDWIREas a supported bank network value (previously onlyACHandSWIFTwere available)
🔧 Fix: Resolved an issue where bank withdrawals could fail for some clients
February 23rd, 2026
🔧 Fix: Resolved an issue where the withdrawal endpoint (POST /v1/baas/transactions/withdrawal) could return a 400 Bad Request with the message "Wallet needs to be linked to a virtual account first" for some wallets that were correctly set up.
February 25th, 2026
🔧 Fix: ACH banking details endpoint (GET /v1/virtual-accounts/banking-details/:walletId?type=ACH) now returns a clear error when a VRN has not been assigned to the wallet, instead of silently omitting the account_number field from the response.
🍃 Enhancement: Customer details endpoint (GET /v1/customers/:id) now includes banking information
The response now includes a bankingInfo object with the customer's virtual account number and VRN (if assigned) from their primary wallet.
New field in response:
| Field | Description |
|---|---|
bankingInfo.virtual_account_number | Virtual account number |
bankingInfo.virtual_reference_number | Virtual Reference Number (VRN) for ACH/FedWire |
Example Response:
{
"id": "customer-uuid",
"type": "PRIVATE",
"email": "john@example.com",
"bankingInfo": {
"virtual_account_number": "256783259046169",
"virtual_reference_number": "9876543210"
},
"portfolios": [...]
}
Notes:
bankingInfois only present if the customer's primary wallet has a virtual accountvirtual_reference_numberis only present if a VRN has been assigned viaPOST /v1/virtual-accounts/assign-vrn
February 27th, 2026
🔧 Fixed POST /internal-transfer endpoint returning null values for all transaction fields. The response now includes transaction type, status, amount, asset, and both source and destination wallet/transaction IDs.
New response format:
{
"message": "The internal transaction successfully executed.",
"data": {
"parentTransactionId": "550e8400-e29b-41d4-a716-446655440000",
"type": "INTERNAL_TRANSFER",
"status": "COMPLETED",
"amount": "100",
"asset": "USD",
"source": {
"walletId": "123e4567-e89b-12d3-a456-426614174000",
"transactionId": "a1b2c3d4-e5f6-7890-1234-567890abcdef"
},
"destination": {
"walletId": "b1abadba-a01f-40d7-a536-e7a99eae1f4b",
"transactionId": "f9e8d7c6-b5a4-3210-fedc-ba0987654321"
},
"createdAt": "2026-02-27T10:00:00.000Z"
},
"traceId": "trace-uuid"
}
How to use the returned IDs:
parentTransactionId— use withGET /v1/transactions?parentTransactionId=Xto retrieve both the debit and credit sidessource.transactionId— the debit (funds leaving) wallet transaction; use withGET /v1/transactions/:iddestination.transactionId— the credit (funds arriving) wallet transaction; use withGET /v1/transactions/:id
March 6th, 2026
🔧 Fix: Resolved an issue where certain incoming ACH deposits were not being recorded. Affected deposits have been automatically reprocessed.
🍃 Enhancement: bankNetwork on bank transactions now supports a new value: UNSPECIFIED. This value is returned when the payment network cannot be determined from the banking partner's notification. Previously supported values (ACH, FEDWIRE, SWIFT) remain unchanged.
March 10th, 2026
🌱 Added new endpoint POST /v1/cards/:cardId/activate for activating cards. For more information, see Activate Card.
💥 Deprecated and removed the DELETE /v1/digital-wallets/:id endpoint for archiving wallets. Wallet archival is no longer available through the B2B API.