On This Page
Subscribing to Webhooks Using OAuth with JWT
The OAuth with JWT flow is an authentication method that is similar to the OAuth 2.0 with
Client Credentials flow, except in OAuth with JWT the client will send a JSON Web Token.
With this option you can bypass domain headers and minimize the need for server-side
authentication checks.
This section describes the tasks that must be accomplished in order to subscribe to
webhooks using OAuth with JSON Web Token (JWT).
Webhooks Subscription Workflow Using OAuth with JWT
Follow these steps to set up your webhooks subscription using OAuth with JWT:
- Set up your server security to receive webhooks notifications. Include app-specific certifications.
- Generate API security keys for authenticating API requests. You must generate separate keys for the testing and production environments.
- Request a digital signature key.
- Send your OAuth credentials.
- Request a product list.
- Subscribe to webhooks event notifications.
Setting Up Server Security
Take these actions to secure your server to receive webhooks notifications.
Allowlist
Allow these IP addresses. Our test and production servers can use either address:
- 198.241.206.21
- 198.241.207.21
Trusting the Root Certificate
Download the certificate, "Visa Corporate Root CA G2" from enroll.visaca.com, and add it to your Java keystore.
Create a P12 File
Follow these steps to create a .p12 file if you are using JSON Web Tokens to secure
communication.
- Log in to theBusiness Center:
- On the left navigation panel, navigate toPayment Configuration > Key Management.
- Click+ Generate key.
- Under REST APIs, selectREST – Certificateand then clickGenerate key.
- ClickDownload key
.
- Create a password for the certificate by entering the password into the New Password and Confirm Password fields, and then clickGenerate key.The .p12 file is downloaded to your desktop.
When you generate one or more keys, you can view the keys on the Key Management page.
Requesting a Digital Signature Key
A digital signature key is required before you can subscribe to webhooks notifications. The API
request to generate the digital signature key is documented in this section. We use the
digital signature key to add a unique signature to each notification. You can use the digital
signature key to validate the integrity of webhooks notifications and prevent replay attacks.
To verify the integrity of a notification payload using the digital signature key, see Notification Validation.
To request the service, use the endpoint specified below. After you send the request, check the
response message to verify that the request was successful. A 200-level response code
indicates success.
For information about response codes, see
Transaction Response Codes
.Endpoint
- Test:POSTapitest.cybersource.com/kms/egress/v2/keys-sym
- Production:POSTapi.cybersource.com/kms/egress/v2/keys-sym
- Production in India:POST api.in.cybersource.com/kms/egress/v2/keys-sym
Required Fields for Requesting a Digital Signature Key
- clientRequestAction
- Set the value toCREATE.
- keyInformation.expiryDuration
- keyInformation.keyType
- Set the value tosharedSecret.
- keyInformation.organizationId
- Set the value to the organization ID of the organization requesting the key.
- keyInformation.provider
- Set the value tonrtd.
- keyInformation.tenant
- Set the value to the organization ID of the organization requesting the key.
Example: Requesting a Digital Signature Key
{ "clientRequestAction": "CREATE", "keyInformation": { "provider": "nrtd", "tenant": "merchantName", "keyType": "sharedSecret", "organizationId": "merchantName" } }
{ "submitTimeUtc": "2021-03-17T06:53:06+0000", "status": "SUCCESS", "keyInformation": { "provider": "NRTD", "tenant": "merchantName", "organizationId": "merchantName", "keyId": "bdc0fe52-091e-b0d6-e053-34b8d30a0504", //ID associated with the key in the key field "key": "u3qgvoaJ73rLJdPLTU3moxrXyNZA4eo5dklKtIXhsAE=", //Base64 encoded key "keyType": "sharedSecret", "status": "Active", "expirationDate": "2022-03-17T06:53:06+0000" }
Sending OAuth Credentials
If you use OAuth, you must send credentials for your OAuth server so that notifications
are authenticated.
To request the service, use the endpoint specified below. After you send the request,
check the response message to verify that the request was successful. A 200-level
response code indicates success.
For information
about response codes, see
Transaction Response
Codes
.Endpoint
- Test:POSTapitest.cybersource.com/kms/egress/v2/keys-sym
- Production:POSTapi.cybersource.com/kms/egress/v2/keys-sym
- Productionin India:POST api.in.cybersource.com/kms/egress/v2/keys-sym
Required Fields for Sending Your OAuth Credentials
- clientRequestAction
- Set the value toSTORE.
- keyInformation.clientKeyId
- Set the value to the OAuth client's username.
- keyInformation.expiryDuration
- Set the value to365.
- keyInformation.key
- Set the value to the client's secret key.
- keyInformation.keyType
- Set the value tooAuthClientCredentials.
- keyInformation.organizationId
- Set the value to the organization ID of the organization requesting the key.
- keyInformation.provider
- Set to the value of theorganizationIdfield that is assigned to the organization sending the request.
- keyInformation.tenant
- Set the value tonrtd.
Example: Sending Your OAuth Credentials
Store oAuth Credentials
{ "clientRequestAction": "STORE", "keyInformation": { "provider": "merchantName", "tenant": "nrtd", "keyType": "oAuthClientCredentials", "organizationId": "merchantName", "clientKeyId": "client username", "key": "client secret", "expiryDuration": "365" } }
{ "submitTimeUtc": "2022-02-18T19:49:52Z", "status": "SUCCESS", "keyInformation": { "provider": "org1", "tenant": "nrtd", "organizationId": "org1", "clientKeyId": "ef400ac1-edfe-406e-94b3-0d73be09a1a0", "keyId": "d8512fb5-1d8c-4f2d-e053-3cb8d30a764c", "key": "KTTY1LLGYR6A2LL4XZTT9W9RGCVJ5Z4XZAP6AFTRUFWLSXX0NX4N88N9EJED3BMM", "keyType": "oAuthClientCredentials", "status": "active", "expirationDate": "2023-02-18T19:49:52Z" } }
Products and Events
Discover the products and events to which you can subscribe by sending an API request to
retrieve the list of all of the products and events that are enabled and configured for your
account. You can subscribe to webhooks only for products and services that are enabled and
configured for your account. The API response includes an array of products with all of the
event types included in the
eventTypes
fields. Requesting a List of Products and Events
To subscribe to a webhook, your account must be enabled for the product associated with the
webhook. To get a list of products and event types that are enabled for your
organization, send a GET request. For more information, see Product and Event Types.
Endpoint
- Test:GETapitest.cybersource.com/notification-subscriptions/v1/products/{organizationId}
- Production:GETapi.cybersource.com/webhooks/notification-subscriptions/v1/products/{organizationId}
- Productionin India:GET api.in.cybersource.com/notification-subscriptions/v1/products/{organizationId}
Example: Requesting a List Products and Event
GEThttps://api.cybersource.com/notification-subscriptions/v1/products/{organizationId}
[ { "productId": "terminalManagement", "eventTypes": [ { "eventName": "terminalManagement.status.update", "payloadEncryption": false }, { "eventName": "terminalManagement.assignment.update", "payloadEncryption": false }, { "eventName": "terminalManagement.reAssignment.update", "payloadEncryption": false } ] } ]
Subscribe to Webhooks Using OAuth with JWT
This section describes the tasks that must be accomplished in order to subscribe to a webhook
using OAuth with a JSON Web Token (JWT). You can only subscribe to one webhook per API
request.
To request the service, use the endpoint specified below. After you send the request, check the
response message to verify that the request was successful. A 200-level response code
indicates success.
For information about response
codes, see
Transaction Response
Codes
.Endpoint
- Test:POSTapitest.cybersource.com/notification-subscriptions/v1/webhooks
- Production:POSTapi.cybersource.com/notification-subscriptions/v1/webhooks
- Production in India:POST api.in.cybersource.com/notification-subscriptions/v1/webhooks
Required Fields for Subscribing to Webhooks Using OAuth with JWT
- eventTypes
- healthCheckUrl
- Required in order to auto-activate the subscription. If you do not send this field, the subscription will be created but not activated. To activate it later, you must send a PATCH request that includes a health check URL. An inactive subscription will not send notifications. For more information, see Health Check URL.
- organizationId
- productId
- For a list of product and event types, see Product and Event Types.
- securityPolicy.securityType
- Set the value tooAuth_JWT.
- securityPolicy.config.oAuthTokenExpiry
- Set the value to365.
- securityPolicy.config.oAuthUrl
- securityPolicy.config.oAuthTokenType
- Set the value toBearer.
- securityPolicy.config.additionalConfig.aud
- securityPolicy.config.additionalConfig.client_id
- securityPolicy.config.additionalConfig.keyId
- securityPolicy.config.additionalConfig.scope
- webhookUrl
Optional Fields for Subscribing to Webhooks Using OAuth with JWT
- description
- healthCheckUrl
- This field is not required in order to create a subscription, but it is required in order to activate it. If you do not send this field during subscription, the subscription is created but not activated. To activate it later, you must send a PATCH request that includes a health check URL. An inactive subscription does not send notifications. For more information, see Health Check URL.
- name
- notificationScope.scopeData
- Required if you submit thenotificationScope.scopefield. All organizations subscribing to the webhook must be listed in the value, separated by commas.
- notificationScope.scope
- For more information, see Notification Scope.
- retryPolicy.deactivateFlag
- See Retry Policy.
- retryPolicy.firstRetry
- See Retry Policy.
- retryPolicy.interval
- See Retry Policy.
- retryPolicy.numberOfRetries
- See Retry Policy.
- retryPolicy.repeatSequenceCount
- See Retry Policy.
- retryPolicy.repeatSequenceWaitTime
- See Retry Policy.
Example: Creating a Webhook Subscription Using OAuth with JWT
{ "name": "My Custom Webhook", "description": "Sample Webhook from Developer Center", "organizationId": "organizationId", "productId": "terminalManagement", "eventTypes": [ "terminalManagement.assignment.update" ], "webhookUrl": "https://MyWebhookServer.com:443/simulateClient", "healthCheckUrl": "https://MyWebhookServer.com:443/simulateClientHealthCheck", "notificationScope": "SELF", "securityPolicy": { "securityType": "oAuth_JWT", "proxyType": "external", "config": { "oAuthTokenExpiry": 365, "oAuthURL": "https://MyWebhookServer.com:443/oAuthToken", "oAuthTokenType": "Bearer", "additionalConfig": { "aud": "idp.api.myServer.com", "client_id": "650538A1-0000-0000-0000-932ABC57AD70", "keyId": "y-00000000000000-eAZ34pR9Ts", "scope": "merchantacq:rte:write" } } } }
{ "organizationId": "organizationId", "productId": "terminalManagement", "eventTypes": [ "terminalManagement.assignment.update" ], "webhookId": "fe46bf08-3918-21ba-e053-a1588d0aeefa", "name": "My Custom Webhook", "webhookUrl": "https://MyWebhookServer.com:443/simulateClient", "healthCheckUrl": "https://MyWebhookServer.com:443/simulateClientHealthCheck", "createdOn": "2023-06-16T21:19:54.667Z", "status": "INACTIVE", "description": "Sample Webhook from Developer Center", "retryPolicy": { "algorithm": "ARITHMETIC", "firstRetry": 1, "interval": 1, "numberOfRetries": 3, "deactivateFlag": false, "repeatSequenceCount": 0, "repeatSequenceWaitTime": 0 }, "securityPolicy": { "securityType": "oAuth_JWT", "proxyType": "external", "digitalSignatureEnabled": "yes", "config": { "oAuthTokenExpiry": 365, "oAuthURL": "https://MyWebhookServer.com:443/oAuthToken", "oAuthTokenType": "Bearer", "additionalConfig": { "aud": "idp.api.myServer.com", "client_id": "650538A1-0000-0000-0000-932ABC57AD70", "keyId": "y-00000000000000-eAZ34pR9Ts", "scope": "merchantacq:rte:write" } } }, "version": "3", "deliveryType": "nrtdCentral", "notificationScope": "SELF" }
Notification Scope
The value of the
notificationScope.scope
field determines which
organizations receive the notification. This field can take any of these values:- SELF
- Subscribes to event notifications for only the organization requesting the webhook subscription.
- DESCENDENTS
- Subscribes to event notifications for all child organizations of the requesting organization.
- CUSTOM
- Subscribes to event notifications for organizations listed in thenotificationScope.scopeDataarray. Organizations must be separated by commas.
Health Check URL
When you subscribe to a webhook, it is recommended that you include a health check URL. While
it is not required to create a subscription, the subscription is not activated until a
health check URL is added to the subscription.
If
deactivateflag=true
was set in the subscription request and your webhook
URL or health check URL become unresponsive, any new notifications will be held and their
respective subscriptions will have a status of SUSPENDED
. When the URLs
becomes responsive, your subscriptions will return to a status of ACTIVE
and
notifications will resume.Providing a health check URL for each webhook implements two features: suspend and resume and
automatic activation.
Suspend and Resume
The webhook delivery framework can detect when a webhook URL is unavailable and suspend the
delivery of notifications. When your webhook URL is available, the webhook framework resumes
delivery of webhook notifications, ensuring that there are no missed notifications. To
implement this feature, you must include the
healthCheckurl
field when
you send the API request that creates the webhook subscription. For more information, see
Set Up Webhooks.Automatic Activation
When you include the
healthCheckUrl
field in the API request that creates a
webhook subscription, the webhook is automatically activated. If you do not add a
health check URL when you create the subscription, the subscription is not
activated. To activate it later, send a PATCH request that includes a health check
URL. An inactive subscription does not send notifications.Subscription Status
A subscription can have one of three statuses:
- ACTIVE
- The subscription is ready to send notifications or is actively sending notifications.
- INACTIVE
- The subscription has not been activated. Add a health check URL to activate. See Health Check URL.
- SUSPENDED
- The subscription was active, but the webhook URL or the health check URL became unreachable. When the URL becomes reachable, the status changes toACTIVEand notifications resume.
Product and Event Types
When you send an API request to create a webhooks subscription, you must include the product
and its associated events to which you are subscribing. You can include only one product
per API request, so you must send separate requests for each product and its associated
events. Each time one of the listed events occurs, you receive a notification. If a
product is not yet available, you receive the notifications when it becomes available.
To obtain a list of products to which you can subscribe, see Requesting a List of Products and Events.
To create a webhooks subscription, set the
productId
field to a value listed
in the product ID column, and set the eventTypes
field array to a
value or values listed in the event types column. These are the supported products and
events and their respective productId
and
eventTypes
field values:Product ID | Event Types | Description |
---|---|---|
alternativePaymentMethods | payments.payments.updated | Notifies you that an alternative payment
transaction's status has been updated. |
Product ID | Event Types | Description |
---|---|---|
fraudManagementEssentials | risk.casemanagement.decision.accept | Notifies you that a Fraud Management Essentials case
has been accepted. |
risk.casemanagement.addnote | Notifies you that a note has been added to a
Fraud Management Essentials case. | |
risk.profile.decision.reject | Notifies you that a transaction was
rejected. | |
risk.casemanagement.decision.reject | Notifies you that a Fraud Management Essentials case
has been rejected. | |
risk.profile.decision.monitor | Notifies you of a profile decision to monitor a
transaction. | |
risk.profile.decision.review | Notifies you of a profile decision to review a
transaction. |
Product ID | Event Types | Description |
---|---|---|
customerInvoicing | invoicing.customer.invoice.send | Notifies you that an invoice has been
sent. |
invoicing.customer.invoice.cancel | Notifies you that an invoice has been
cancelled. | |
invoicing.customer.invoice.paid | Notifies you that an invoice has been
paid. | |
invoicing.customer.invoice.partial-payment | Notifies you that an invoice has been partially
paid. | |
invoicing.customer.invoice.reminder | Notifies you 5 days before the invoice payment is due. This
event is triggered if you have invoice reminders enabled in your
invoice settings. | |
invoicing.customer.invoice.overdue-reminder
| Notifies you 1 day after the invoice payment is due. This event
is triggered if you have invoice reminders enabled in your
invoice settings. |
Product ID | Event Types | Description |
---|---|---|
cns | cns.report.keyExpiration.detail
| Notifies you that a key is expiring. |
Product ID | Event Types | Description |
---|---|---|
recurringBilling | rbs.subscriptions.charge.failed | Notifies you of a recurring payment
failure. |
rbs.subscriptions.charge.pre-notified | Notifies you of an upcoming recurring
payment. | |
rbs.subscriptions.charge.created | Notifies you of successful recurring
payment. |
Product ID | Event Types | Description |
---|---|---|
tokenManagement | tms.networktoken.updated | Notifies you of a network token's change in
expiration date or status (suspend, resume, or
deactivate). |
tms.networktoken.provisioned | Notifies you when a network token provision for
an instrument identifier token has been
successful. |
Example: Product and Events in a Webhook Subscription
"productId": "tokenManagement", "eventTypes": [ "tms.networktoken.provisioned", "tms.networktoken.updated", "tms.token.pan_updated", "tms.token.created", "tms.token.updated" ]
Related Information
Set Up WebhooksNotification Format
Each event notification contains headers and the body of the message.
Notification Headers
These headers are sent with every notification. Some headers are duplicates of the fields in
the body.
- V-C-signature
- Contains the digital signature, which can be used for validating the security of the notification.
- V-C-event-type
- Type of event that generated the notification.
- V-C-organization-id
- Identifier of the organization that subscribed to the notification.
- V-C-product-name
- Name of the product for which the event occurred.
- V-C-request-type
- New or retry.
- V-C-retry-count
- Number of times the notification was resent.
- V-C-transaction-trace-id
- Identifier of the notification attempt. For example, every time a notification is retried, each attempt has a different transaction trace ID and the same notification ID.
- v-c-webhook-id
- Identifier of the webhook subscription that generated the notification.
Notification Body
The body of the message contains fields associated with the notification itself and the
payload of the event that generated the notification.
- webhookId
- Identifier of the webhook subscription that generated the notification.
- transactionTraceId
- Identifier of the notification attempt. For example, every time a notification is retried, each attempt has a different transaction trace ID and the same webhook ID.
- productId
- Identifier of the product that generated the event.
- organizationId
- Identifier of the organization that subscribed to the notification.
- eventType
- The type of event that generated the notification.
- eventDate
- Timestamp of the event.
- payload
- The data generated by the event.
- requestType
- New or retry.
Example: Notification Payload
Invoicing Webhook Notification
POST /test HTTP/1.1 Host: invoicetest.example.com Content-Length: 1647 Content-Type: application/json User-Agent: Vert.x-WebClient/3.9.8 V-C-Event-Type: invoicing.customer.invoice.send V-C-Organization-Id: invoicetest V-C-Product-Name: customerInvoicing V-C-Request-Type: NEW V-C-Retry-Count: 0 V-C-Signature: t=168506218354;keyId=facdaf45-db00-233c-e053-5a588d0a743a;sig=kJgSHwHrRgUmXJdaSSqtPVzOTMlV3SW90WAFIfPj4XA= V-C-Transaction-Trace-Id: 8c01a8e9b3334d19528d9b69a21fe797ebaf8dd3dee52f422dd699af26bd866-0 V-C-Webhook-Id: fc8a9385-723e8e28-e053-a2588e0a536d { "notificationId":"fc8f1cae-1232-5dd-e053-a0588e0a5eeb", "retryNumber":0, "eventType":"invoicing.customer.invoice.send", "eventDate":"2023-05-25T17:49:40.309-07:00", "webhookId":"fc8a9385-723e-8e28-e053-a2588e0a536d", "payloads":[ { "data":{ "merchantZip":"12345", "thankYou":"Thank you for your business!", "subject":"You've received an invoice 202203789 from Company, Inc.", "dueDate":"2023-05-25", "link":"Click the link below to view and pay the invoice.", "body":"You have a new invoice from Company, Inc. for 102.00 ALL due on 2023-05-25.", "merchantState":"OH", "merchantName":"Company, Inc.", "button":"VIEW AND PAY INVOICE", "invoiceBalance":"102.00", "merchantAddress2":" ", "invoiceNumber":"20220389", "payerName":"Firstname Lastname", "customMessage":"Thank you for your business. By clicking the view and pay invoice you agree to the terms and conditions here: https://paymenttermsandconditions.example.com", "currency":"ALL", "merchantCity":"Placeville", "emailTo":"Person@example.com", "eventType":"invoicing.customer.invoice.send", "balanceAmount":"102.00", "organizationID":"invoicetest", "merchantPhone":"321-321-3211", "emailLanguage":"en-us", "invoiceUrl":"https://businesscentertest.cybersource.com/ebc2/invoicing/payInvoice/u2wJqUKII4FsqtIrZx51lUuvYr5Msz23nqIx12xqJhs7wqT6Th2mJcDOYHSC5hE?version=v2.1", "merchantAddress":"39 E. Road St", "correlationID":"dceb3ce-d787-453c-84a3-ce33b141cc76", "hello":"Hello Person," }, "preferences":{ "contacts":[ { "firstName":"Invoicing", "lastName":"Email", "contact":"person@example.com", "type":"EMAIL" } ] }, "organizationId":"invoicetest", "metadata":{ "from.displayName":"Company, Inc.", "reply.email":"noreply@example.com", "sentBy":"Invoice" } } ] }