> **Source:** https://knowledge.leegality.com/document-execution/api/security/payload-encryption > **Site:** Leegality Knowledge Base — https://knowledge.leegality.com > **About:** Leegality is a document execution platform covering eSigning, stamps, NeSL, workflows, and REST API integration. > **Navigation:** Every article on this site has a plain-text version at `.txt` (this format). To get an index of all articles with their `.txt` links, read: https://knowledge.leegality.com/llms.txt > **AI Guide:** For instructions on how to navigate this knowledge base as an AI agent, read: https://knowledge.leegality.com/ai-readable.txt --- # Payload Encryption Payload encryption adds an additional security layer to API requests, responses, and webhook notifications beyond standard HTTPS/TLS/SSL protocols. #### API Payload Encryption ### Pre-requisites Before enabling API payload encryption: 1. **Verify plan**: Contact Leegality customer support (support@leegality.com) to confirm your license supports API payload encryption. 2. **Key-Pair Exchange**: Exchange public keys with Leegality over secure email (bi-directional) - **Public Keys** - Leegality's public keys are shared with customers to download and use to encrypt API requests. - Customer-managed pubic keys are shared with Leegality to encrypt API responses. - **Private Keys** - Leegality's private keys are used to decrypt the API requests sent by the customer. - Customer-managed private keys are used to decrypt the API responses sent by Leegality. 3. **Specify User email IDs**: Provide the list of user email IDs that will make encrypted API calls. Leegality will map your public certificate to these user IDs ### How It Works Leegality uses **AES-256-CBC** to encrypt the payload content. The AES key and IV (Initialization Vector) used for encryption are bundled together into a 48-byte structure — 32 bytes for the AES key followed by 16 bytes for the IV. This bundle is called the **salt**, which is then RSA-encrypted with the recipient's public key before being sent alongside the payload. The encryption is built on a two-key system — each party holds a public key and a private key. Public keys are shared openly; private keys never leave their owner. | Direction | Encrypted with | Decrypted with | |-----------|---------------|----------------| | Your request → Leegality | Leegality's public key *(Leegality shared with you)* | Leegality's private key | | Leegality's response → You | Your public key *(You shared with Leegality)* | Your private key | ### Sending Encrypted Requests To send an encrypted request to a Leegality API, follow these steps: 1. Create the standard request payload as per API documentation 2. Generate a 256-bit AES key and IV (Initialization Vector) 3. Encrypt the request payload using the AES key (AES-256-CBC) and encode the result with Base64 format — this is the **`payload`** value 4. Combine AES key + IV into a 48-byte bundle (bytes 0–32 is AES key and bytes 32–48 is IV) 5. Encrypt the bundle with Leegality's public key using RSA and Base64 encode the result — this is the **`salt`** value 6. Send the request with the `content-encoding: encrypted` header and this body structure: ```bash curl --location 'https://app.leegality.com/api/v3.0/{endpoint}' \ --header 'X-Auth-Token: YOUR_API_TOKEN' \ --header 'Content-Type: application/json' \ --header 'content-encoding: encrypted' \ --data '{ "salt": "BASE64_ENCODED_ENCRYPTED_AES_KEY_AND_IV", "payload": "BASE64_ENCODED_ENCRYPTED_PAYLOAD" }' ``` ```mermaid flowchart LR A["Create request payload"] --> B["Generate 256-bit AES key + IV"] B --> C["Encrypt payload with AES key"] B --> D["Combine AES key + IV into 48-byte bundle"] C --> E["Base64 encode → payload value"] D --> F["Encrypt bundle with Leegality's public key"] F --> G["Base64 encode → salt value"] E --> H["Send request with content-encoding: encrypted"] G --> H ``` ### Decrypting API Responses When you send an encrypted request, Leegality's response is also encrypted — using your public key. You must decrypt it to read the response. Encrypted responses from Leegality have this structure: ```json { "salt": "BASE64_ENCODED_ENCRYPTED_AES_KEY_AND_IV", "payload": "BASE64_ENCODED_ENCRYPTED_RESPONSE" } ``` To decrypt: 1. Decrypt the salt using your organization's private key (RSA) 2. Extract AES key (bytes 0-31) and IV (bytes 32-47) from the decrypted salt 3. Decrypt the payload using the extracted AES key and IV (AES-256-CBC) 4. Parse the decrypted JSON response > **Info** > > HTTP status codes and error messages are NOT encrypted. Only the response payload is encrypted. ### Additional Resources A sample Java application for encryption, decryption, and related steps is available at the [Leegality Encryption Utility](https://gitlab.leegality.com/leegality-public/encryption-decryption-util) repository. #### Webhook Payload Encryption ### Pre-requisites Before enabling webhook payload encryption: 1. **Verify License**: Contact Leegality customer support to confirm your license supports webhook payload encryption 2. **Share Public Certificate**: Send your **RSA public key in PEM format** (file extension: `.cer.txt`) to Leegality over secure email. You retain the corresponding private key for decryption 3. **Receive Profile ID**: Leegality will configure your public certificate and provide a **Webhook Profile ID** 4. **Configure Profile ID**: Add the Webhook Profile ID against each invitee when sending documents > **Info** > > - If you configure both Payload Encryption and [Custom Webhook Headers](https://knowledge.leegality.com/document-execution/api/security/custom-webhook-headers), both are mapped to a single **Webhook Profile ID** — you don't need separate IDs > - An organisation can have multiple Profile IDs with different combinations > - Profile IDs are optional — if no Profile ID is passed, no encryption or custom headers are applied ### Configuring Webhook Profile ID **Via Dashboard**: 1. When creating or editing a workflow, navigate to invitee configuration 2. Go to **Invitee Level Options** for the invitee(s) who should receive encrypted webhooks 3. Under **Add custom URLs and webhooks** section 4. Enter the Webhook Profile ID in the **Webhook Profile ID** field **Via API**: Add `profileId` in the webhook object for each invitee when sending documents: ```json { "invitees": [ { "name": "John Doe", "email": "john@example.com", "webhook": { "profileId": "YOUR_WEBHOOK_PROFILE_ID", "url": "https://your-domain.com/webhook" } } ] } ``` > **Tip** > > Only invitees with a Profile ID configured will receive encrypted webhook payloads. Invitees without a Profile ID will receive standard (non-encrypted) webhooks. ### How It Works Leegality uses **AES-256-CBC** to encrypt webhook payloads. When a webhook is triggered for an invitee with a Profile ID configured: 1. Leegality generates a 256-bit AES key and IV (Initialization Vector) 2. Encrypts the webhook payload with the AES key — Base64 encoded, this is the **`payload`** value 3. Encrypts the AES key + IV bundle with your public key using RSA — Base64 encoded, this is the **`salt`** value 4. Sends the encrypted webhook to your endpoint: ```json { "salt": "BASE64_ENCODED_ENCRYPTED_AES_KEY_AND_IV", "payload": "BASE64_ENCODED_ENCRYPTED_WEBHOOK_PAYLOAD" } ``` ### Decrypting Webhook Payloads When your endpoint receives a webhook, the body will contain two fields — `salt` and `payload` — both Base64 encoded. To read the webhook content, you need to decrypt them using your private key: 1. Decrypt the `salt` using your private key (RSA) to obtain the 48-byte bundle 2. Extract the AES key (bytes 0–32) and IV (bytes 32–48) from the decrypted bundle 3. Decrypt the `payload` using the extracted AES key and IV (AES-256-CBC) 4. Parse the decrypted JSON and process the webhook content