Enable Message-Level Encryption
Message-level encryption (MLE) encrypts the payload of a message to prevent tampering. This section explains how to create the key that is necessary to decrypt encrypted payloads.
The webhook notification service requires X.509 certificates instead of raw public keys for MLE. The service uses:
- Symmetric Encryption: AES-GCM with 256-bit keys
- Asymmetric Encryption: RSA-OAEP with 2048-bit keys
- Format: JSON Web Encryption
- Separate key pairs for request and response transactions
Before You Begin
- OpenSSL must be installed on your system.
- You must have access to terminal/command line.
- You must have appropriate permissions to create the asymmetric key in the system.
Prepare
Open a terminal and navigate to a secure location for storing your key pairs:
mkdir -p ~/webhooks-keyscd ~/webhooks-keysGenerate a Key
Run these command with no line breaks, but change these values:
- Replace
RequestKeywith the API key that you created in the API keys setup. - Replace
YourOrgwith your account's organization ID.
openssl req -x509 -newkey rsa:2048 -keyout request_private.pem -out request_certificate.pem -days 365 -nodes -subj "/CN=RequestKey/O=YourOrg/C=US" && cat request_certificate.pem | grep -v "BEGIN CERTIFICATE" | grep -v "END CERTIFICATE" | tr -d '\n' && echoRegister a Key
Use the REST API to register and store your certificate. Each webhook subscription requires its own unique asymmetric certificate.
Endpoints
Send a POST request to one of these endpoints:
POST /kms/egress/v2/keys-asym
POST /kms/egress/v2/keys-asym
POST /kms/egress/v2/keys-asym
Example: Registering Your Certificate
{ "clientRequestAction": "STORE", "keyInformation": { "provider": "<set this to your organization ID>", "tenant": "nrtd", "keyType": "publickey", "organizationId": "<set this to your organization ID>", "pub": "//this must be one line with no breaks MIIDbDCCAlQCCQD4lcSlmasmCTANBgkqhkiG9w0BAQsFADB4MQswCQYDVQQGEwJVUzELMAkGA1UECAwCVFgxDzANBgNVBAcMBkF1c3RpbjENMAsGA1UECgwEVGVzdDEOMAwGA1UECwwFVGVzdDIxDjAMBgNVBAMMBVRlc3QzMRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3QuY29tMB4XDTIxMDgwOTE0MTcxNFoXDTIyMDgwOTE0MTcxNFoweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlRYMQ8wDQYDVQQHDAZBdXN0aW4xDTALBgNVBAoMBFRlc3QxDjAMBgNVBAsMBVRlc3QyMQ4wDAYDVQQDDAVUZXN0MzEcMBoGCSqGSIb3DQEJARYNdGVzdEB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMcHQWZRETqim3XzUQlAiujFEvsHIi1uJZKj+1lvPH36Ucqo3ORcoh/MM/zxVdahjhSyyp7MHuKBWnzft6bFeDEul6qKWGPAAzaxG/2xZSV3FggA9SyAZEDUpJ6mblwqm/EY4KmZi1FrNBUHfW2wwaqDexHPRDesRG6aI7Wuu4GdQUUqoTa2+Nv7kVgEDmGcfIjoWkGKHe+Yan95EITrq4jEFCE5Tg/vERnMvHfK2SovENZ13/pnwFYbeh1kfJSBzWW7yq8AyQAgAE9iqJXbJ/MAasir2vjUQ2+Hcl7WbkpoVjLqDt3rzV1T0Bsd4T9SC3wij9qjJSxa6vAgV4xn6bECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEADuMrtYW1Sf0IsZ4ZD9ipjUrFuTxqh+0M5Jk8h0QqAXEHA/MawedlU3JmE3NB/UR82/XUwdmtObGnFANuUQQ+8WMFpcNo/Sq2kg7juneHZroRh72o73UUMtHWHzo8s0fXElNal8h3SaAAnjMblCiN+gM1RvWMvhGrMTXp2XAcdIezXf8/FOZLlzOF9QylbSk1U4ayWBag6MydkxgHjkPKdShZROEm0oz/O7J/gNp/r7J8F42Rw9MmJh9qH3SFre13nQa8V7Kg+dJHZ/jpGtSlDHAxO0SSTrPXkwB+iBJ6hSkiL/J2Ep+lYHqVe3p5NXMOlTtJdbU4enHeLkD6PazKTw", "expiryDuration": "365" }}{ "submitTimeUtc": "2026-01-22T14:36:31Z", "status": "SUCCESS", "keyInformation": { "provider": "384259", "tenant": "nrtd", "organizationId": "384259", "keyId": "937dfa75-acff-4f5b-9aab-66a49455ae04", "pub": "MIIDbDCCAlQCCQD4lcSlmasmCTANBgkqhkiG9w0BAQsFADB4MQswCQYDVQQGEwJVUzELMAkGA1UECAwCVFgxDzANBgNVBAcMBkF1c3RpbjENMAsGA1UECgwEVGVzdDEOMAwGA1UECwwFVGVzdDIxDjAMBgNVBAMMBVRlc3QzMRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3QuY29tMB4XDTIxMDgwOTE0MTcxNFoXDTIyMDgwOTE0MTcxNFoweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlRYMQ8wDQYDVQQHDAZBdXN0aW4xDTALBgNVBAoMBFRlc3QxDjAMBgNVBAsMBVRlc3QyMQ4wDAYDVQQDDAVUZXN0MzEcMBoGCSqGSIb3DQEJARYNdGVzdEB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMcHQWZRETqim3XzUQlAiujFEvsHIi1uJZKj+1lvPH36Ucqo3ORcoh/MM/zxVdahjhSyyp7MHuKBWnzft6bFeDEul6qKWGPAAzaxG/2xZSV3FggA9SyAZEDUpJ6mblwqm/EY4KmZi1FrNBUHfW2wwaqDexHPRDesRG6aI7Wuu4GdQUUqoTa2+Nv7kVgEDmGcfIjoWkGKHe+Yan95EITrq4jEFCE5Tg/vERnMvHfK2SovENZ13/pnwFYbeh1kfJSBzWW7yq8AyQAgAE9iqJXbJ/MAasir2vjUQ2+Hcl7WbkpoVjLqDt3rzV1T0Bsd4T9SC3wij9qjJSxa6vAgV4xn6bECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEADuMrtYW1Sf0IsZ4ZD9ipjUrFuTxqh+0M5Jk8h0QqAXEHA/MawedlU3JmE3NB/UR82/XUwdmtObGnFANuUQQ+8WMFpcNo/Sq2kg7juneHZroRh72o73UUMtHWHzo8s0fXElNal8h3SaAAnjMblCiN+gM1RvWMvhGrMTXp2XAcdIezXf8/FOZLlzOF9QylbSk1U4ayWBag6MydkxgHjkPKdShZROEm0oz/O7J/gNp/r7J8F42Rw9MmJh9qH3SFre13nQa8V7Kg+dJHZ/jpGtSlDHAxO0SSTrPXkwB+iBJ6hSkiL/J2Ep+lYHqVe3p5NXMOlTtJdbU4enHeLkD6PazKTw", "keyType": "publickey", "status": "active", "expirationDate": "2022-08-09T14:17:14Z" }}Required Fields
| Field | Description |
|---|---|
clientRequestAction | Set the value to STORE. |
keyInformation. | Set the value to the name of the organization ID of the account. |
keyInformation. | Set the value to nrtd. |
keyInformation. | Set the value to publickey. |
keyInformation. | Set the value to the name of the organization ID of the account. |
keyInformation. | Set the value to the X.509 certificate that you generated. IMPORTANT: The certificate is generated with line breaks. You must remove the line breaks before adding it to this field. Do not include the --BEGIN-- and --END-- lines. See Example: Registering Your Certificate. |
keyInformation. | Set the value to 365. |
Secure Your Subscription
Here are some tips to ensure that your keys remain secure.
- Store private keys in a secure location with restricted permissions.
- Never commit private keys to version control.
- Rotate certificates before expiration.
- Use environment variables or secure vaults for production deployments.
- Keep back-up copies of your private keys in a secure location.
Secure Your Private Key
Keep your request_private.pem file secure. This private key is required to decrypt incoming webhook notifications. To modify the permissions so that only the file owner can read and write to the files, use this command:
chmod 600 request_private.pemView Your Key
To verify your certificate details, use this command.
openssl x509 -in request_certificate.pem -text -nooutThanks for your feedback!
Last published: October 28, 2026