Guides
Guides/Webhooks

Webhooks

Receive real-time event notifications for transaction and deposit lifecycle changes.

Webhooks

FV Bank sends an HTTP POST to your configured callback URL whenever a transaction event occurs for one of your clients.


Payload Envelope

Every webhook has this top-level structure:

json
{
  "Event":   "<EVENT_TYPE>",
  "Id":      "<unique delivery UUID>",
  "Message": "<human-readable summary>",
  "Data":    { ... }
}

Data Field Reference

FieldTypeNotes
CreatedDateISO 8601Timestamp of when the transaction was originally created (e.g. 2026-06-29T08:59:45.000Z)
TransactionNumberstringUnique FV Bank transaction reference (e.g. FV000726845). Use this to reconcile with your internal records
TypestringIdentifies the payment or deposit rail (ACH, Wire, International Wire, Cross-Border, Stablecoin, etc.) — see Type Reference
AmountstringTransaction amount as a decimal string (e.g. "20.00")
BalancenumberAccount balance at the time the webhook was delivered, reflecting the effect of this transaction (e.g. 397885.60)
FromstringDisplay name of the sender or originating party
TostringDisplay name of the recipient or beneficiary
CurrencystringCurrency code for the transaction (e.g. "USD")
DescriptionstringHuman-readable transaction description. Not present on all event types (optional)
AdditionalDataarrayRail-specific metadata as label/value pairs — e.g. IMAD/OMAD for wire transfers, document IDs, stablecoin network info. Format: [{ "label": "...", "value": "..." }] (optional)
OldStatusstringPrevious transaction status before this change. Present only in TRANSACTION_STATUS_UPDATED events
NewStatusstringUpdated transaction status. Possible values: IN PROCESS, COMPLETED, RETURNED, FAILED. Present only in TRANSACTION_STATUS_UPDATED events

Signature Verification

Every request includes a signature header:

code

x-signature: <HMAC-SHA256 hex>

Computed over JSON.stringify(Data) using your Broker Client Secret.

javascript
const crypto = require('crypto');
const hmac = crypto.createHmac('sha256', BROKER_CLIENT_SECRET);
const expected = hmac.update(JSON.stringify(req.body.Data)).digest('hex');
const valid = crypto.timingSafeEqual(
  Buffer.from(req.headers['x-signature']),
  Buffer.from(expected)
);

Always verify the signature before processing any webhook.


Fiat Payment Webhooks

Covers Domestic ACH, Domestic Wire, International Wire, FVNet, and Stablecoin Withdraw transactions.

Event Flow

code

TRANSACTION_CREATED
TRANSACTION_AUTHORIZED      (compliance approved)
TRANSACTION_STATUS_UPDATED  (status changes during bank processing)
     OR
TRANSACTION_DENIED
TRANSACTION_CANCELLED
TRANSACTION_EXPIRED
TRANSACTION_RETURNED

TRANSACTION_CREATED

Triggered when a payment is initiated. Pending compliance review — funds have not moved.

json
{
  "Event": "TRANSACTION_CREATED",
  "Id": "7d026990-7f3a-4e15-b00e-9af258b22309",
  "Message": "Transaction created",
  "Data": {
    "CreatedDate": "2026-06-26T10:36:26.687Z",
    "TransactionNumber": "FV000726845",
    "Type": "Payment - Domestic Wire",
    "Amount": "20.00",
    "Balance": 397905.60,
    "From": "Your Company Name",
    "To": "Beneficiary Name",

TRANSACTION_AUTHORIZED

Triggered when compliance approves the payment. Processing begins.

json
{
  "Event": "TRANSACTION_AUTHORIZED",
  "Id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
  "Message": "Transaction authorized",
  "Data": {
    "CreatedDate": "2026-06-29T08:59:45.000Z",
    "TransactionNumber": "FV000726845",
    "Type": "Payment - Domestic Wire",
    "Amount": "20.00",
    "Balance": 397885.60,
    "From": "Your Company Name",
    "To": "Beneficiary Name",

TRANSACTION_STATUS_UPDATED

Triggered when the payment status changes after funds movement begins. May fire multiple times.

OldStatus and NewStatus are added to Data for this event only.

NewStatusMeaning
IN PROCESSBank is processing the transfer
COMPLETEDTransfer successfully settled
RETURNEDReturned by the receiving bank
FAILEDFailed during processing
json
{
  "Event": "TRANSACTION_STATUS_UPDATED",
  "Id": "a7b8c9d0-e1f2-3456-0123-567890123456",
  "Message": "The member transaction status changed",
  "Data": {
    "CreatedDate": "2026-06-29T08:59:45.000Z",
    "TransactionNumber": "FV000726845",
    "Type": "Payment - Domestic Wire",
    "Amount": "20.00",
    "Balance": 397885.60,
    "From": "Your Company Name",
    "To": "Beneficiary Name",

TRANSACTION_DENIED / CANCELLED / EXPIRED / RETURNED

Terminal states — no further events follow.

EventMessageWhen
TRANSACTION_DENIEDTransaction deniedCompliance rejected
TRANSACTION_CANCELLEDTransaction cancelledCancelled before processing
TRANSACTION_EXPIREDTransaction expiredAuth window elapsed
TRANSACTION_RETURNEDTransaction returnedReversed by receiving bank

These events share the same payload shape as TRANSACTION_CREATED.


Fiat Deposit Webhooks

Covers Wire, ACH, International Wire, and Custodial Transfer deposits with full lifecycle events.

Stablecoin deposits only emit DEPOSIT_RECEIVED. No further lifecycle events (authorized, denied, etc.) fire for stablecoin.

Event Flow

code

DEPOSIT_RECEIVED
DEPOSIT_AUTHORIZED   (funds credited)        ← success
     OR
DEPOSIT_DENIED       (compliance rejected)   ← terminal
DEPOSIT_EXPIRED      (auth window elapsed)   ← terminal
DEPOSIT_CANCELLED    (cancelled OR chargeback/reversal) ← terminal

DEPOSIT_RECEIVED

Triggered when a deposit arrives. Pending compliance review — funds are not yet credited.

json
{
  "Event": "DEPOSIT_RECEIVED",
  "Id": "d0e1f2a3-b4c5-6789-3456-890123456789",
  "Message": "Transaction created",
  "Data": {
    "CreatedDate": "2026-06-29T10:59:45.000Z",
    "TransactionNumber": "FV000726900",
    "Type": "Deposit Domestic Wire",
    "Amount": "50000.00",
    "Balance": 75000.00,
    "From": "Sender Bank Name",
    "To": "Your Company Name",

Stablecoin Deposit

Only DEPOSIT_RECEIVED fires for stablecoin deposits — no authorized, denied, or cancelled events follow.

json
{
  "Event": "DEPOSIT_RECEIVED",
  "Id": "f8a9b0c1-d2e3-4567-1234-678901234567",
  "Message": "Transaction created",
  "Data": {
    "CreatedDate": "2026-06-29T16:59:50.000Z",
    "TransactionNumber": "FV000726903",
    "Type": "Stablecoin Deposit",
    "Amount": "1000.00",
    "Balance": 26000.00,
    "From": "FV Bank",
    "To": "Your Company Name",

DEPOSIT_AUTHORIZED

Triggered when compliance approves the deposit. Funds are now credited. Balance reflects the updated amount.

json
{
  "Event": "DEPOSIT_AUTHORIZED",
  "Id": "a3b4c5d6-e7f8-9012-6789-123456789012",
  "Message": "Transaction authorized",
  "Data": {
    "CreatedDate": "2026-06-29T10:59:45.000Z",
    "TransactionNumber": "FV000726900",
    "Type": "Deposit Domestic Wire",
    "Amount": "50000.00",
    "Balance": 125000.00,
    "From": "Sender Bank Name",
    "To": "Your Company Name",

DEPOSIT_DENIED / EXPIRED / CANCELLED

Terminal states — same payload shape as DEPOSIT_RECEIVED.

EventMessageWhen
DEPOSIT_DENIEDTransaction deniedCompliance rejected the deposit
DEPOSIT_EXPIREDTransaction expiredNo compliance action within the allowed timeframe
DEPOSIT_CANCELLEDTransaction cancelledCancelled by compliance before processing
DEPOSIT_CANCELLEDTransaction returnedDeposit reversed or charged back after receipt

DEPOSIT_CANCELLED fires for two distinct scenarios — use the Message field to distinguish between a cancellation and a chargeback/reversal.


Cross-Border Payment Webhooks

Covers all cross-border rails (SEPA, Wire, Faster Payments, CLABE, etc.).

Event Flow

code

TRANSACTION_CREATED
TRANSACTION_AUTHORIZED      (compliance approved)
TRANSACTION_STATUS_UPDATED  (status changes during processing)
     OR
TRANSACTION_DENIEDterminal
TRANSACTION_CANCELLEDterminal
TRANSACTION_EXPIREDterminal

Cross-border payments do not emit TRANSACTION_RETURNED. Chargebacks apply to domestic rails only.

Currency is USD. The destination currency is identified from Data.Type.


TRANSACTION_CREATED (Cross-Border)

json
{
  "Event": "TRANSACTION_CREATED",
  "Id": "e741c4bc-a6b0-466a-bf23-f4f20b799f39",
  "Message": "Transaction created",
  "Data": {
    "CreatedDate": "2026-06-26T08:26:44.531Z",
    "TransactionNumber": "FV000726696",
    "Type": "Payment - Cross Border - Clabe",
    "Amount": "1.16",
    "Balance": 736.16,
    "From": "Your Company Name",
    "To": "Beneficiary Name",

TRANSACTION_STATUS_UPDATED (Cross-Border)

Same structure as fiat — includes OldStatus and NewStatus in Data.

json
{
  "Event": "TRANSACTION_STATUS_UPDATED",
  "Id": "a5b6c7d8-e9f0-1234-8901-345678901234",
  "Message": "The member transaction status changed",
  "Data": {
    "CreatedDate": "2026-06-29T08:59:50.000Z",
    "TransactionNumber": "FV000726950",
    "Type": "Payment - Cross Border - SEPA",
    "Amount": "2000.00",
    "Balance": 17500.00,
    "From": "Your Company Name",
    "To": "Beneficiary Name",


Counterparty & Instrument Status Webhooks

These webhooks are triggered when a Counterparty record status changes to Active or Awaits Approval (Rejected), and when a Counterparty Instrument record status changes to Active or Rejected.

The payload for these webhooks includes a top-level Date field (ISO 8601 timestamp) in addition to the standard Event, Id, Message, and Data fields.

Data Field Reference

FieldTypeNotes
BrokerIdstringInternal identifier for the GMA partner broker
UserIdstringIdentifier of the customer user associated with the record
OldStatusstringStatus of the record before this change
NewStatusstringStatus of the record after this change
RecordIdstringUnique identifier of the counterparty or instrument record
RecordTypestringType of the record — COUNTERPARTY or COUNTERPARTY_INSTRUMENT

Events

EventMessageWhen
COUNTERPARTY_ACTIVATEDCounterparty activatedCounterparty status changed to Active
COUNTERPARTY_INSTRUMENT_ACTIVATEDCounterparty Instrument activatedInstrument status changed to Active
COUNTERPARTY_AWAITING_ACTIVATIONCounterparty awaiting activationCounterparty status changed to Awaits Approval (Rejected)
COUNTERPARTY_INSTRUMENT_REJECTEDCounterparty Instrument rejectedInstrument status changed to Rejected

Sample — COUNTERPARTY_AWAITING_ACTIVATION

json
{
  "Event": "COUNTERPARTY_AWAITING_ACTIVATION",
  "Id": "244badfa-64fb-4436-b00a-b43789f8e6ee",
  "Message": "Counterparty awaiting activation",
  "Date": "2026-07-15T06:14:23",
  "Data": {
    "BrokerId": "<broker-id>",
    "UserId": "<user-id>",
    "OldStatus": "Pending",
    "NewStatus": "Awaits approval",
    "RecordId": "<record-id>",
    "RecordType": "COUNTERPARTY"

Type Reference

Fiat Payments

Data.Type
Payment - Domestic ACH
Payment - Domestic Wire
Payment - International Wire
FVNet Payment
Stable Coin Withdraw

Fiat Deposits

Data.Type
BUS ACH Deposit
Credit IAT ACH
Deposit Domestic Wire
Deposit Bridge Wire
Business Deposit
Deposit Third Party Custodial Transfer
Stablecoin Deposit

Cross-Border Payments

Data.TypeDestination Currency
Payment - Cross Border - AED Domestic PaymentsAED
Payment - Cross Border - AED Wire PaymentsAED
Payment - Cross Border - ARS Domestic PaymentsARS
Payment - Cross Border - BRL Domestic PaymentsBRL
Payment - Cross Border - CAD Domestic PaymentsCAD
Payment - Cross Border - CAD Wire PaymentsCAD
Payment - Cross Border - SEPAEUR
Payment - Cross Border - EUR Wire PaymentsEUR
Payment - Cross Border - Faster PaymentsGBP
Payment - Cross Border - GBP Wire PaymentsGBP
Payment - Cross Border - HKD Domestic PaymentsHKD
Payment - Cross Border - HKD Wire PaymentsHKD
Payment - Cross Border - JPY Domestic PaymentsJPY
Payment - Cross Border - JPY Wire PaymentsJPY
Payment - Cross Border - ClabeMXN
Payment - Cross Border - MXN Wire PaymentsMXN
Payment - Cross Border - SGD Domestic PaymentsSGD
Payment - Cross Border - SGD Wire PaymentsSGD
Payment - Cross Border - ZAR Domestic PaymentsZAR
Payment - Cross Border - ZAR Wire PaymentsZAR

Best Practices

  • Verify signatures on every request before processing
  • Deduplicate using Id — retries use the same Id
  • Use TransactionNumber to reconcile with your internal records
  • Use DEPOSIT_AUTHORIZED (not DEPOSIT_RECEIVED) to credit funds — the deposit is not confirmed until authorized
  • Handle terminal states (DENIED, CANCELLED, EXPIRED, RETURNED) as failure paths requiring attention

Search guide books, endpoints, paths, or parameters

↑↓navigateopenEscclose