Webhooks

clock 6-minute read calender 2.2.0 | updated Nov. 12, 2024

Timely and automated payment status notifications

KeyBank’s payment webhooks provide timely and automated payment status notifications without the need for constant API polling or manual checks.

We currently facilitate alerts for both ACH and wire transaction status changes. You get near real-time updates whenever a specific payment event occurs, like a posted ACH transaction or a completed wire transfer.

Requirements

To subscribe to webhook alert notifications for ACH, Wire, or RTP transactions, you must be a commercial customer or fintech partner of KeyBank. Only authorized API consumers can subscribe to this feature.  

  • For existing clients, reach out to your Payments Advisor to start the subscription process.
  • For new clients, you will first need to onboard with KeyBank (see our Getting Started Guide for the basic process). In addition, you will be asked to provide a few more details like:
    • Type of alert subscription (see alert codes)
    • A decision if the pre-production and production subscriptions accounts will be the same or different
    • Expected volumes per day/month/year

KeyBank recommends that destination application always have authentication. To reduce setup time for webhook subscriptions while maintaining system integrity and security, we recommend these guidelines:

  1. Use Basic Authentication (BasicAuth) which involves providing KeyBank with a unique username and password for your application. 
  2. KeyBank will send a Base64 encoded version of the credential to Authorization header of your HTTP request. 
  3. Connect securely with a TLS connection for an encrypted, safe exchange of data. 

If you have a specialized needs or circumstances that require secure alternatives rather than BasicAuth, speak with your KeyBank Payment Advisor. This may extend setup time. 

Got you hooked?

Check out some more content about our webhooks:


Alert notifications are triggered by specific payment status events and are sent in the form of an HTTP POST request. KeyBank can send up to 100 alerts per API call. After receiving an alert notification, KeyBank expects you to send an HTTP 2XX status code in response within 10 seconds and the response needs to adhere to KeyBank's format for an alert response.

Each payment webhook alert notification has an alertNotification object that is made up of two parts:

  • alertHeader: The header information gives you basic information about the request like date and time sent, the alert code, and a unique notification identifier.
  • alertBody: The body information contains transaction details. Each of the fields will be present in the request even if there is no data retrieved for a particular field. Fields that have no data show the null value.

Both the alertHeader and alertBody can vary by event type, ACH or Wire/RTP. The alertHeader for Wire/RTP notification contains the payType field that specifies if is a wire or RTP alert while the ACH alert header does not have this field. The alertBody fields are also different based on each event type as defined by the alert code.

Each alert notification contains the alert code for the payment status event that occurred. There is an alert code for Wire/RTP and ACH to monitor all payment status events related to that transaction type.

Alert code types
  • Wire/RTP alert code = AL00901
  • ACH alert code = AL00906

Note, with a latest specification update, all ACH payment events are now managed with alert code AL00906. This one code consolidates the legacy ACH alert codes: AL00902 (ACH Collected), AL00903 (ACH Posted), AL00904 (ACH Returned), AL00905 (ACH Notification of Change). 

Before you begin

All KeyBank APIs require certificates, user credentials, and certain permissions. Check out our Getting Started Guide to learn more.


HEADER FIELDTYPEDESCRIPTION
alertSentDateAndTimestringDate and time the alert was sent. Format: (YYYY-MM-DD)T(HH:MM:SS)Z
alertCodestringAlert code. Valid values: AL00906
eapAlertGUIDstringUnique alert notification identifier.
BODY FIELDTYPEDESCRIPTION
transactionStatusstringThe status of the ACH transaction. Valid values: COLLECTED, RETURNED, SETTLED
traceNumberstringThe unique number for the transaction provided by the originator.
parNumberstringThe unique PAR number assigned to the the transaction by the ACH product processor.
transactionAmountnumberThe dollar amount of the transaction.
collectionDatestringDate the transaction was processed. Format: YYYY-MM-DD
settlementDatestringThe date the transaction settlement occurred. Format: YYYY-MM-DD
transactionCodestringTwo-digit code identifying the account type at the receiving financial institution.
transactionDescriptionstringDescription about the purpose of the transaction.
authorizedCustomerNamestringAuthorized customer name
standardEntryClassCodestringThree-digit Standard Entry Class (SEC) code based on Nacha rules. Valid values: CCD, CTX, PPD, TEL, WEB
receivingAccountNumberstringAccount number of the person or institution receiving the funds. 
receivingCustomerIdentificationNumberstringThe customer identification number for the person receiving the transaction.
receivingCompanyNamestringCompany name of the institution getting the funds. 
originatingAccountNumberstringAccount number of the ACH transaction originator.
originatingCustomerIdentificationNumberstringOriginating customer identification number
returnReasonCodestringThe code associated with the reason for returning the ACH transaction. The code is the letter 'R' for reason followed by a two-digit numeric code. Format: R00
returnReasonDescriptionstringDescription as to why the ACH transaction is returned.
returnDatestringDate of the returned transaction to the ACH system. Format: YYYY-MM-DD
notificationOfChangeAddendaCountstringCount of change notifications for addenda records.
internationalAddendaCountstringCount of international addenda records.
addendaCountstringCount of addenda records.

Request example (ACH)

{
"alertNotificationRequest": [  
	{  
	"alertNotification": {
	  "alertHeader": {
		"alertSentDateAndTime": "2024-07-07T16:25:08Z",
		"alertCode": "AL00906",
		"eapAlertGUID": "4g0fda4b-156f-483c-98ae-bd8ccab266h0"
		},
	"alertBody": {
		"transactionStatus": "COLLECTED",
		"traceNumber": "41033956478656",
		"parNumber": "22010008879477",
		"transactionAmount": "287.40",
		"collectionDate": "2024-01-12",
		"settlementDate": "2024-01-12",
		"transactionCode": "22",
		"transactionDescription": "PAYMENT",
		"authorizedCustomerName": "HIGHMARK INC.",
		"standardEntryClassCode": "CCD",
		"receivingAccountNumber": "00000000001000004133",
		"receivingCustomerIdentificationNumber": "65A658990",
		"receivingCompanyName": "LEHIGH GASTROENTEROLOG",
		"originatingAccountNumber": "00000000001000005244",
		"originatingCustomerIdentificationNumber": "7498659450",
		"originatingCompanyName": "HIGHMARK INC.",
		"returnReasonCode": "R29",
		"returnReasonDescription": "Corporate Customer Advises Not Authorized",
		"returnDate": "2024-01-03",
		"notificationOfChangeAddendaCount": "1",
		"internationalAddendaCount": "0",
		"addendaCount": "0"
		}
	  }
	}
  ]
}

The Wire/RTP alertBody identifies the status of the payment event in the tranBusnStatusCode field. 

The Wire and RTP statuses listed show the final status values. You may get an intermittent status that is not list in this table. Go to Data values > Wire and RTP webhook statuses to view the full list.

STATUSDESCRIPTION
AbandonedPayment is manually forced to not complete payment processing. Payment will not complete workflow.
CancelledPayment was cancelled. Payment will not complete workflow.
CompletedPayment processed successfully and completes the workflow.
FatalA serious error has occurred. Payment will not complete workflow.
Future Warehouse CancelledPayment was cancelled from Future Warehouse queue. Payments enter the Future Warehouse queue if the payment missed the payment network cutoff time and moves to a future business date. When the future business date arrives, the payment network re-enters the payment in the workflow to reach Future Warehouse Cancelled.
RejectedPayment was rejected by the network. Payment will not complete workflow.
ReturnedPayment was returned by receiving bank.
HEADER FIELDTYPEDESCRIPTION
alertSentDateAndTimestringDate and time the alert was sent. Format: (YYYY-MM-DD)T(HH:MM:SS)Z
alertCodestringAlert code. Valid values: AL00901
payTypestringIdentifies if the payment type was a Wire or RTP transaction. Valid values: WIRE, RTP
eapAlertGUIDstringUnique alert notification identifier.
BODY FIELDTYPEDESCRIPTION
crOrDbCodestringIdentifies the transaction type as credit or debit. Valid values: C (credit), D (debit)
crArngNumstringAccount number of the credit account.
crArngTypeCodestringType code of the credit account.
crArngBankNumstringBank number of the credit account.
crTranCurrencyCodestringTransaction currency code of the credit account.
dbArngTypeCodestringType code of the debit account
dbTranCurrencyCodestringTransaction currency code of the debit account.
requestReferenceNumberstringUnique identification number for an originating wire or RTP transaction. This number is limited to 32 characters.
crIpIdstringCustomer number associated with the credit account.
crIpNmstringCustomer name associated with the credit account.
dbArngNumstringAccount number of the debit account.
dbArngBankNumstringBank number of the debit account.
dbIpIdstringCustomer number associated with the debit account.
dbIpINmstringCustomer name associated with the debit account.
payNotifyTsstringTimestamp of the payment event.
wireEventNmstringPayment status code
tranAmtstringDollar amount of the transaction.
tranExecutedDtstringDate the transaction is executed. Format: YYYYMMDD
federalReferNumstringFederal reference number
sndngBankReferNumstringReference number attached to a wire, issued by the sending bank.
tranIdstringUnique transaction identifier
tranBusnStatusCodestringTransaction business status code
wireDirectionCodestringIndicates the direction of the transaction.
tranTypestringType of transaction.
tranValueTypeCodestringIdentifies the value of a transaction.
wireProcessTypeCodestringWire processing type code
benefitAbastringABA routing number of the beneficiary.
benefitArngNumstringAccount number of the beneficiary.
benefitIpAddrLinestringAddress lines 1-7 (array) of the beneficiary.
benefitBicCodestringBIC number of the beneficiary.
benefitBankAbaNumstringABA routing number of the beneficiary's bank.
benefitBankArngNumstringAccount number of the beneficiary's bank.
benefirBankAddrLinestringAddress lines 1-7 (array) of the beneficiary's bank.
benefitBankBicCodestringBIC number of the beneficiary's bank.
benefitBankNmstringName of the beneficiary's bank.
intrmdryBankAbaNum1stringABA routing number of the intermediary bank 1.
intrmdryBNankAddrLine1stringAddress lines 1-7 (array) of the intermediary bank 1.
intrmdryBankNm1stringName of the intermediary bank 1.
intrmdryBicCode1stringBIC number of the intermediary bank 1.
intrmdryBankAbaNum2stringABA routing number of the intermediary bank 2.
intramdryBankAddrLine2stringAddress lines 1-7 (array) of the intermediary bank 2.
intrmdryBankNm2stringName of the intermediary bank 2.
intrmdryBicCode2stringBIC number of the intermediary bank 2.
intrmdryBankAbaNum3stringABA routing number of the intermediary bank 3.
intrmdryBankAddrLine3stringAddress lines 1-7 (array) of the intermediary bank 3.
intrmdryBankNm3stringName of the intermediary bank 3.
intrmdryBicCode3stringBIC number of the intermediary bank 3.
orgntngBankAbaNumstringABA routing number of the wire originator's bank.
orgntngBankAddrLinestringAddress lines 1-7 (array) of the wire originator's bank.
orgntngBankBicCodestringBIC number of the wire originator's bank.
orgntngBankNmstringName of the wire originator's bank.
orgntngAba1stringABA routing number of the originator 1.
orgntngArngNum1stringAccount number of the originator 1.
orgntngIpNm1stringName of the originator 1.
orgntngIpAddrLine1stringAddress lines 1-7 (array) of the originator 1.
orgntngAba2stringABA routing number of the originator 2.
orgntngArngNum2stringAccount number of the originator 2.
orgntngIpNm2stringName of the originator 2.
orgntngIpAddrLine2stringAddress lines 1-7 (array) of the originator 2.
orgntngAba3stringABA routing number of the originator 3.
orgntngArngNum3stringAccount number of the originator 3.
orgntngIpNm3stringName of the originator 3.
orgntngIpAddrLine3stringAddress lines 1-7 (array) of the originator 3.
crVirtualNumstringVirtual account number of the credit account.
dbVirtualNumstringVirtual account number of the debit account.

Request example (Wire/RTP)

{
  "alertNotificationRequest": [
  {
	"alertNotification": 
	  "alertHeader": {
		"alertSentDateAndTime": "2023-02-1159T10:20:56Z",
		"alertCode": "AL00901",
		"payType": "WIRE",
		"eapAlertGUID": "f4d88cd2-446c-3cc4-9330-aa123456789"
		},
	  "alertBody": {
		"crOrDbCode": "C",
		"crArngNum": "359123456789",
		"crArngTypeCode": "DDA",
		"crArngBankNum": "0101",
		"crTranCurrencyCode": "USD",
		"dbArngTypeCode": "DDA",
		"dbTranCurrencyCode": "USD",
		"requestReferenceNumber": "4630123-20240212161123",
		"crIpId": "999997",
		"crIpNm": "BANKOFTEST",
		"dbArngNum": "201907987654321",
		"dbArngBankNum": "0101",
		"dbIpId": "30472222",
		"dbIpNm": "Test Name",
		"payNotifyTs": "1673615327943",
		"wireEventNm": "WirePaymentTransactionEvent",
		"tranAmt": "12.79",
		"tranExecutedDt": "20240112",
		"federalReferNum": "null",
		"sndngBankReferNum": "null",
		"tranId": "US23010987654321",
		"tranBusnStatusCode": "RegulatoryFilter",
		"wireDirectionCode": "OUTBOUND",
		"tranType": "null",>
		"tranValueTypeCode": "N",
		"wireProcessTypeCode": "null",
		"benefitAba": "null",
		"benefitArngNum": "3435656765",
		"benefitIpAddrLine": "250 Delaware Ave St",
		"benefitBicCode": "KEYBUS33 XXX",
		"benefitBankAbaNum": "null",
		"benefitBankArngNum": "null",
		"benefitBankAddrLine": "250 Delaware Ave St",
		"benefitBankBicCode": "KEYBUS33 XXX",
		"benefitBankNm": "KeyBank National Association",
		"intrmdryBankAbaNum1": "null",
		"intrmdryBankAddrLine1": "null",
		"intrmdryBankNm1": "KeyBank National Association",
		"intrmdryBicCode1": "21300077",
		"intrmdryBankAbaNum2": "null",
		"intrmdryBankAddrLine2": "null",
		"intrmdryBankNm2": "BANKOFTEST",
		"intrmdryBicCode2": "KEYBUS33 XXX",
		"intrmdryBankAbaNum3": "null",
		"intrmdryBankAddrLine3": "null",
		"intrmdryBankNm3": "null",
		"intrmdryBicCode3": "null",
		"orgntngBankAbaNum": "null",
		"orgntngBankAddrLine": "null",
		"orgntngBankBicCode": "null",
		"orgntngBankNm": "null",
		"orgntngAba1": "null",
		"orgntngArngNum1": "123456789",
		"orgntngIpNm1": "TEST COMPANY 1, LLC",
		"orgntngIpAddrLine1": "127 Public Sq, Cleveland,OH 44114,US",
		"orgntngAba2": "null",
		"orgntngArngNum2": "null",
		"orgntngIpNm2": "null",
		"orgntngIpAddrLine2": "null",
		"orgntngAba3": "null",
		"orgntngArngNum3": "null",
		"orgntngIpNm3": "null",
		"orgntngIpAddrLine3": "null"
		"crVirtualNum": "953456789",
		"dbVirtualNum": "953654321"
		}
	  }
	}
  ]
}
                    

The top level alertNotificationResponse object is an array of alertAcknowledgment objects. Because KeyBank can send up to 100 alerts per API call, each alert notification sent must be responded to with its own alertAcknowledgment object. The format of the response needs to adhere to the format specified here.

FIELDTYPEDESCRIPTION
alertStatusstringStatus of the alert notification.
confirmationGUIDstringAPI customer unique ID for the alert notification.
alertRecievedDateAndTimestringDate and time the alert was received. Format: (YYYY-MM-DD)T(HH:MM:SS)Z
eapAlertGUIDstringUnique alert notification identifier passed through from the request.
messagestringFree-form text field to describe the response.

Successful response

{
  "alertNotificationResponse": [
  {
    "alertAcknowledgment": {
    "alertStatus": "SUCCESS",
    "confirmationGUID": "5f0ada5b-056f-483c-98ae-ac6ccab269c1",
    "alertRecievedDateAndTime": "2021-11-19T10:31:12Z",
    "eapAlertGUID": "f4d88cd2-446c-3cc4-9330-aa123456789",
    "message": "Successfully submitted the request"
    }
  }
 ]
}

Unsuccessful response

{
  "alertNotificationResponse": [
  {
    "alertAcknowledgment": {
      "alertStatus": "FAILURE",
      "confirmationGUID": "5f0ada5b-056f-483c-98ae-ac6ccab269c1",
      "alertRecievedDateAndTime": "2021-11-19T10:31:12Z",
      "eapAlertGUID": "f4d88cd2-446c-3cc4-9330-aa123456789",
      "message": "Required parameter(s) not found: [fieldName(s)]"
    }
  }
]
}

If your webhook receiver/handler encounters an error, KeyBank expects you to send one of the following HTTP status codes:

  • 400 Invalid input
  • 401 Authentication error
  • 403 Authorization error
  • 500 Internal error

Only the HTTP 500 error codes will prompt the retry mechanism. If you have one of the HTTP 400 error codes, you are expected to troubleshoot the issue. If you cannot find a resolution, please contact your Payments Advisor or Technical Account Manager.

 

The retry mechanism is trigger for any backend error issues, typically associated with HTTP 500's status codes.  With a unsuccessful HTTP 5XX response, the KeyBank retry mechanism will attempt to deliver a failed alert notification for 24 hours after the original failed notification. The retry attempts follow this schedule:

  • 3 attempts, each attempt every 30 seconds
  • 6 attempts, each attempt every 90 minutes
  • 3 attempts, each attempt every 5 hours
Attempt numberTime between attemptsTime elapsed since first alert
1-330 seconds30 seconds - 1.5 minutes
4-990 minutes1.5 - 9 hours
10-125 hours14 - 24 hours

After the 24-hour window, the notification fails and there are no more additional retry attempts. Notify your Payments Advisor if there is an outage for more than 24 hours or if you have an outage planned for your systems that extends past a 24-hour period. You can also notify us with our Support form.

To inquire about a payment event after 24 hours, you must use the ACH Inquiry or Wire Inquiry APIs.

 

ReleaseAPI versionChange descriptionImpact
August 20242.2.0
  • We introduce the version 2 of our Webhooks. This API is sleek! For ACH alerts, the alert codes (AL00902, AL00903, AL00904, AL00905) have been consolidated into a single and new code, AL00906.
HIGH
April 20241.1.0
  • For Wire and RTP webhook alert notifications, dbTranCurrencyCode and dbAngTypeCode are in the alert body.
  • Added the requestReferenceNumber to the alert body for Wire and RTP alert notification. If this parameter has a value, it will return in the alert body for RTP or Wire notifications.
MID
December 20231.1.0
  • Remove all leading zeros for the following account parameters:
    • crArngNum
    • dbArngNum
    • accountNumber
LOW
August 20231.0.1
  • Published on the Developer Portal.
 

Impact levels

  • LOW: This is a minor change or enhancement that does not alter the operations of the API. Upgrading to the latest specifications is preferable but not required.
  • MID: The previous API version is valid and operates, but does not contain latest enhancements. You need to update your specifications to get these enhancements.
  • HIGH: The previous API version is no longer operable. You must upgrade to the latest specifications to access and use this API product.

YAML file download