Webhooks
This is the official reference documentation for the SVB Webhooks API. Please see the authentication documentation for access information.
The Webhooks API follows the same conventions as SVB’s other APIs. Please see the documentation on API conventions for more information.

Overview

Webhooks allow SVB clients to receive event notifications on their SVB API activity. Clients can listen for events, get notified of updates on their payment activity in real-time and react on the received updates. 

What is a webhook 

SVB webhook notification is an API driven one-way data sharing capability that is triggered by an event. Users receive HTTP callback notifications on previously subscribed event types. 

 

Postman Collection with examples

 

Use case - ACH API

Once an API request is submitted on the ACH API, there are various statuses that a payment can move into. The client will generally need to check for any changes by polling the API endpoint.

This is no longer needed if the webhook subscription is in place to receive ACH payment status updates. The client can:

  1. Subscribe to ACH payment status event type.
  2. Receive event notifications by SVB when the payment status changes.
  3. Integrate their internal system to update payment status and react appropriately to the received event notifications.

Steps to configure a webhook

  1. Based on the SVB product being used, client identifies the list of event types that they are interested in.
  2. Client authenticates with the Authentication API and receives an access token.
  3. Client subscribes to event types, specifying where they want to receive the callback notifications.
  4. Once SVB processes the appropriate events to trigger the webhook, SVB informs the client at the callback address specified on the subscription.

Retries

If delivery of the event notification fails for any reason, SVB will retry to send the event notification at a later time. Below are the retry intervals to resend a failed event notification. 

 

Attempt Time
 First Attempt  2 seconds
 Second Attempt  4 seconds
 Third Attempt  8 seconds
 Fourth Attempt  16 seconds

 

After above attempts are exhausted, SVB will repeat the process again for 3 more times with an interval of 1 hour. After 4 retries, if the event notification is still not sent then the notification status will be updated to "FAILED".

Technical Integration

1 - Authentication

Webhooks use the same authentication mechanism as ACH v2, Wires and VCN v2 APIs. More information on SVB oAuth 2.0 can be found on the authentication page. 

 

2 - Event Types

Clients can subscribe to below event types. Subscription to multiple event types and multiple subscriptions to same event type are both allowed.

API Product Event Name Description
ACH ach.statuscritical  Triggers events for returns or corrections on ACH transfers.
ACH ach.statusadvice  Triggers for non-critical events on ACH transfers, changes from one status to another (i.e. updates to statuses: processing, processed, successful, canceled). 
ACH ach.information  Effective date adjustments on the submitted ACH API request (i.e. changing effective date of original request due to a holiday).
Wires wires.status  Status changes of a wire payment.
VCN  vcn.created  Notification when a virtual card is created using the VCN API.
VCN vcn.canceled  Notification when a virtual card is cancelled using the VCN API.
VCN vcn.clearings  Notification when a virtual card clearing is received for a transaction. 
VCN vcn.authorizations  Notification when a virtual card authorization is received for a transaction.

 

3 - Subscription

Subscription to the event type can be made using the endpoint: /v2/event/subscriptions

As the client obtains their "access_token" and "jws-signature", POST call can be made to create a subscription to the webhook event. 

Webhooks Subscription example request auth

access_token is set using Authorization: Bearer Token

Webhooks Subscription example request headers

JWS signature token is included in the header (note: request body of the JWS token call must match the request body of the actual subscription request below)

Webhooks Subscription example request body

 

Optional Encryption - To Verify the Sender of an Event Notification 

Clients have the option to specify a secret key to encrypt and generate a signature for the event notification. 

  • As the event notification is received, the client can generate their signature using the same algorithm and compare this signature against the signature specified on the received webhook event.
  • If the two signatures match, the sender of the event notification can be confirmed.
  • More information can be found on the Signature Verification section.

Webhooks Subscription example request secret key

 

4 - Receiving Event Notification

Once step 3 is completed, the integration is complete. Clients will start listening for events on the callback address that they used to subscribe for the event type in step 3.

Below is an example of such event (ach.information), arriving at the callback address specified by the client. Please see further examples here

Webhooks Receiving Event Notification

 

5 - Signature Verification (Optional)

Once the client receives an event notification (as in step 4), the client can then fetch the HmacSHA256 encrypted signature from the header (named X-Signature). 

Webhooks Signature Verification

 

This signature will then be compared against the signature client generates as below:

  • Client will generate an encrypted signature using HmacSHA256 algorithm with parameters:  timestamphttp methodcallback url and event notification payload.

 

Sample Java Signature Verification Code

    String timeStamp = request.getHeader("x-timestamp")

    String httpMethod = "POST"

    String callbackUrl = { clientCallbackUrl } 

    String payload = { receivedNotificationPayload }

    String data = new String().join("\n", timeStamp, httpMethod, callbackUrl, payload));

    String key = { clientSecretKey }

    String signature = new HmacUtils(HmacAlgorithms.HMAC_SHA_256, key).hmacHex(data);

    String incomingSignature = request.getHeader("x-signature");

    if(signature.equals(incomingSignature) { 

        // consume and process notification

     } else {

        // sender of the notification cannot be verified

     }

Example Event Notifications

ACH

1 ach.information
=================

Example :

{
  "data": {
    "event_id": "aaaaaaaa-cbbb-482d-9c4d-dccb7831e680",
    "event_type_name": "ach.information",
    "created_at": "2022-08-10T22:44:59.429148Z",
    "payload": {
      "delta": [
        {
          "field_name": "effective_entry_date",
          "old_value": "2022-08-10",
          "new_value": "2022-08-11"
        }
      ],
      "ach_transfers_id": "aaaaaaaa-193b-4040-b579-cc897a9cc4c2",
      "modified_at": "2022-08-10T22:44:59.299728Z"
    }
  }

2. ach.statusadvice : PENDING -> PROCESSING
===========================================

{
  "data": {
    "event_id": "aaaaaaaa-e461-4a7e-b425-fde3341cf2b0",
    "event_type_name": "ach.statusadvice",
    "created_at": "2022-08-10T22:53:41.855917Z",
    "payload": {
      "delta": [
        {
          "field_name": "status",
          "old_value": "PENDING",
          "new_value": "PROCESSING"
        }
      ],
      "ach_transfers_id": "aaaaaaaa-6c23-4ba4-a4e3-e7fcc3c86dc7",
      "modified_at": "2022-08-10T22:53:41.459418Z"
    }
  }
}

3. ach.statusadvice : PROCESSING -> SUCCEEDED
===========================================

{
  "data": {
    "event_id": "aaaaaaaa-e461-4a7e-b425-fde3341cf2b0",
    "event_type_name": "ach.statusadvice",
    "created_at": "2022-08-10T22:53:41.855917Z",
    "payload": {
      "delta": [
        {
          "field_name": "status",
          "old_value": "PROCESSING",
          "new_value": "SUCCEEDED"
        },
{
          "field_name": "fed_trace_number",
          "new_value": "111111111111111"
      ],
      "ach_transfers_id": "aaaaaaaa-6c23-4ba4-a4e3-e7fcc3c86dc7",
      "modified_at": "2022-08-10T22:53:41.459418Z"
    }
  }
}


4. ach.statuscritical : PROCESSING  -> FAILED
============================================

{
  "data": {
    "event_id": "aaaaaaaa-e461-4a7e-b425-fde3341cf2b0",
    "event_type_name": "ach.statuscritical",
    "created_at": "2022-08-10T22:53:41.855917Z",
    "payload": {
      "delta": [
        {
          "field_name": "status",
          "old_value": "PROCESSING",
          "new_value": "FAILED"
        },
       {
          "field_name": "return_code",
          "new_value": "RO1"

        }
      ],
      "ach_transfers_id": "aaaaaaaa-6c23-4ba4-a4e3-e7fcc3c86dc7",
      "modified_at": "2022-08-10T22:53:41.459418Z"
    }
  }
}

5. ach.statuscritical : PROCESSING  -> CORRECTED
============================================

{
  "data": {
    "event_id": "aaaaaaaa-e461-4a7e-b425-fde3341cf2b0",
    "event_type_name": "ach.statuscritical",
    "created_at": "2022-08-10T22:53:41.855917Z",
    "payload": {
      "delta": [
        {
          "field_name": "status",
          "old_value": "PROCESSING",
          "new_value": "CORRECTED"
        },
       {
          "field_name": "return_code",
          "new_value": "CO1"

        },
   {
          "field_name": "corrected_data",
          "new_value": "999999999"
        }
      ],
      "ach_transfers_id": "aaaaaaaa-6c23-4ba4-a4e3-e7fcc3c86dc7",
      "modified_at": "2022-08-10T22:53:41.459418Z"
    }
  }
}

Virtual Card (VCN)

1. vcn.created
======================
{
  "data": {
    "event_id": "aaaaaaa6-ba18-411a-933c-c08be4f34a48",
    "event_type_name": "vcn.created",
    "created_at": "2022-08-10T22:53:21.079193Z",
    "payload": {
      "id": "76aaaaaa-88ef-4b1b-be5a-603a28f939b9",
      "status": "APPROVED",
      "rcn_id": "4440",
      "rcn_alias": "AAARCN",
      "valid_starting_on": "2022-08-09",
      "valid_ending_on": "2022-12-12",
      "available_balance": 70000,
      "total_card_amount": 70000,
      "transactions_max": 1000,
      "per_transaction_max": 70000,
      "per_transaction_min": 0
    }
  }
}

2. vcn.canceled
===================
{
  "data": {
    "event_id": "aaaaaaa6-1cbf-484b-adb3-ad2ab3089da0",
    "event_type_name": "vcn.canceled",
    "created_at": "2022-08-10T23:24:41.571761Z",
    "payload": {
      "id": "0e85babb-c650-4e19-9157-fa07e126e13b",
      "status": "CANCELED"
    }
  }
}

3. vcn.clearings
========================

{
  "data": {
    "event_id": "aaaaaaa6-2953-47a7-a733-819651713719",
    "event_type_name": "vcn.clearings",
    "created_at": "2022-08-11T19:37:57.606678Z",
    "payload": {
      "rcn_id": "4440",
      "rcn_alias": "AAARCN",
      "MCC": "22",
      "vcn_id": 1234567,
      "MerchantId": "03-00000869",
      "AcquirerICA": "",
      "ApprovalCode": "028937",
      "ClearingType": "DEBIT",
      "MerchantName": "ACME1",
      "BillingAmount": "100",
      "MCCDescription": "ELECTRONIC SALES",
      "MerchantAmount": "100",
      "SettlementDate": "2022-01-20T00:00:00.000Z",
      "AuthorizationDate": "2022-01-19T00:00:00.000Z",
      "BillingCurrencyCode": "GBP",
      "MerchantCurrencyCode": "GBP",
      "TxnExchangeRate": "1.000000",
      "card_number": "556338######1234",
      "BanknetReferenceNum": "000ABCDEFGHI",
      "MasterCardFinancialTransactionId": "0000000001234",
      "AcquirerReferenceData": "85481472020000000001234",
      "vcn_uuid": "aaaaaaa6-3391-4c75-80ce-93957988774b"
    }
  }
}




4. vcn.authorizations
========================

    {
  "data": {
    "event_id": "aaaaaaa6-8bd4-4d19-9e97-e67a91da1f9c",
    "event_type_name": "vcn.authorizations",
    "created_at": "2022-08-11T19:16:56.706665Z",
    "payload": {
      "rcn_id": "4440",
      "rcn_alias": "Travel Expense RCN",
      "MCC": "5542",
      "vcn_id": 1234567,
      "MerchantId": "03-00000869",
      "ApprovalCode": "502359",
      "MerchantName": "AMCE2",
      "BillingAmount": "7550",
      "MCCDescription": "FUEL DISPENSER AUTOMATED",
      "MerchantAmount": "7550",
      "BillingCurrencyCode": "USD",
      "MerchantCurrencyCode": "USD",
      "card_number": "************6213",
      "BanknetReferenceNum": "A",
      "vcn_uuid": "aaaaaaa6-4eac-4708-acb0-0b16fe4ce5fd",
      "AdviceReasonCode": "650",
      "CompanyId": 123456,
      "IssuerResponse": "Approved",
      "MerchantCity": "Jasper",
      "MerchantStateOrCountryCode": "TN",
      "MessageTypeIndicator": "Unknown message type indicator: 9110",
      "PurchaseRequestCompanyGuid": "AAAAAA995197AAAAAA206CB494B560E5AAAAAA2A2BD21D89612EF4A18358ECC777DCF1494921797",
      "PurchaseRequestIssuerGuid": "AAAAAA5E4C4B4AAAAAA5991E64A1E0745AAAAAAB2510CE48EB537011DCED3C483669D61494938440",
      "ReplacementAmountsTransactionAmount": 1200,
      "ReplacementAmountsSettlementAmount": 1200,
      "ReplacementAmountsBillingAmount": 1200,
      "SystemTraceAuditNumber": "011111",
      "TransactionDateTime": "2022-11-03T10:16:11Z",
      "VcnResponse": "Valid",
      "ClearingReferenceNumber": "A"
    }
  }
}