Optimization Protection
Public keys
A public key is a cipher that allows you to verify if the source of the callback notification is valid and from a secure J.P. Morgan system.
How public keys work
Step 1: Webhook notification delivery
Notifications sends the following headers as part of the webhook notification delivery:
- Signature: Digital signature of the notification payload.
- Key-ID: Key ID of the key pair used for the digital signature.
- Signing algorithm: Algorithm used to generate the digital signature. The value will be EC (Elliptic Curve).
Step 2: Obtaining the public key
To verify the signature, the receiving party needs the public key of the key pair used to sign the payload. The public key can be obtained by following these steps:
- Use the public key endpoint (/public-keys) to access the public key.
- The API returns the response in JSON Web Key Set (JWKS) format.
- Check the expiry date and time of the public key in the value of the field
expto plan your key rotation ahead of time. - Convert the JWKS format into PEM (Base64 encoded) format for the key with the EC
kty(key type)
Step 3: Signature verification
To verify the signature, you must perform the following steps:
- Take the Base64 encoded key obtained from Step 2.
- Decode the Base64 encoded public key.
- Use the decoded public key to create a public key object with the EC algorithm using your preferred cryptography library.
- Decode the Base64 encoded signature received in the notification signature header.
- Use the verify signature functionality in your cryptography library to validate the decoded signature with your public key object and notification body using the SHA256withECDSA algorithm
The following is an example of how you can retrieve the public key information.
HTTP method: GET
Endpoint: /public-keys
Scenario: Retrieving a public key
Json
{
"keys": [
{
"kid": "6599834191ad40b79a309d7a4702a1db",
"kty": "RSA",
"n": "0A6tY59w6ue-V54Abtvju7xcHyYdLGnbTyf2YvmFk9-D08ImUkrzVH4eANVzR-9ch3Ih3WvXqe52h1mtKLnAxlb4elg5WRMEJdEatUKyWRKJyiop4x7bk3b2OlTTqm83SITrLqp4BE35H05BQ1bPBFoSZLz3i2xQNzV4cOUOfdplR4iGiFrkUna1C9nGmgXcPayT-S6DasoKF_rhvoruoDXgitK6IjuIBBCe3Lt4XGK1_EJr4WTqTBlbnFD7WMqHMnXqQuXw6MgOTn5dstOOXIr8gqFaTtxyGDPWx4DMR4n4kd0VdYYHmQhumm5kKHzP0l6a1WKJHu0IdP45F-Bk5o61MMYvpzgTiEwcjOu70IrVZxx_DCZ9uE9KUBHjsnAkvwwY21waB6llNWBm4oLmGLbBb7IVP-enwFipFqsv9A_CWhu-gigyf6HIKJuvtFT3bD1n5LRFVoC-y_FAJs0vettPAwuTfWfjvzcPkV58wSdg4ulflgRAjgwB_eDE52cB",
"e": "AQAB",
"use": "sig",
"exp": "2025-10-23T11:30:25.477Z"
},
{
"kid": "4d56e5f1db9a430e8dd8b5d916aa72e9",
"kty": "EC",
"crv": "P-256",
"x": "qNB5v_fJaN69N0EQU_ERDeGEjzGs7MWIXeXD1gKCPl0",
"y": "msXtGZRc_qHXYMjI0AaJNAJ-lrf8hhpLPoDa7XSZZoM",
"use": "sig",
"exp": "2026-02-21T13:15:28.755Z"
}
]
}