> ## Documentation Index
> Fetch the complete documentation index at: https://docs.moduluslabs.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Encryption & JWE Tokens

> Learn how to encrypt and decrypt payloads using JWE tokens

## Overview

The Modulus Labs QR API uses **JWE (JSON Web Encryption)** tokens to encrypt request and response payloads. This ensures that sensitive payment data is protected and maintains integrity throughout the entire transaction lifecycle.

<Info>
  **What is JWE?** JSON Web Encryption is a standard for encrypting data in a compact, URL-safe format. It ensures that the payload cannot be read or modified during transit.
</Info>

## Why JWE Encryption?

<CardGroup cols={2}>
  <Card title="Data Protection" icon="shield">
    Sensitive payment information is encrypted end-to-end
  </Card>

  <Card title="Integrity Verification" icon="check-circle">
    Any tampering with the token will cause verification to fail
  </Card>

  <Card title="Compliance" icon="scale-balanced">
    Meets security standards for financial transactions
  </Card>

  <Card title="Standardized" icon="globe">
    Uses industry-standard encryption algorithms
  </Card>
</CardGroup>

## Encryption Specifications

The QR API requires specific encryption algorithms for JWE tokens:

| Parameter              | Value              | Description                   |
| ---------------------- | ------------------ | ----------------------------- |
| **Content Encryption** | `A256CBC-HS512`    | AES-256-CBC with HMAC SHA-512 |
| **Key Wrap Algorithm** | `A256KW`           | AES-256 Key Wrap              |
| **Content Type**       | `application/json` | JSON payload format           |

## Your Encryption Key

Along with your Secret Key, Modulus Labs will provide you with an **Encryption Key** for JWE operations:

```
6eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG
```

<Warning>
  Store your Encryption Key securely! Never commit it to version control or expose it in client-side code.
</Warning>

## Recommended Libraries

Use these well-tested libraries for creating and decrypting JWE tokens:

<Tabs>
  <Tab title="Node.js">
    ### jose

    The most popular JWT/JWE library for Node.js:

    ```bash theme={null}
    npm install jose
    ```

    [Documentation](https://github.com/panva/jose)
  </Tab>

  <Tab title=".NET">
    ### jose-jwt

    Comprehensive JWT/JWE support for .NET:

    ```bash theme={null}
    dotnet add package jose-jwt
    ```

    [Documentation](https://github.com/dvsekhvalnov/jose-jwt)
  </Tab>

  <Tab title="PHP">
    ### jwt-framework

    Modern JWT/JWE library for PHP:

    ```bash theme={null}
    composer require web-token/jwt-framework
    ```

    [Documentation](https://web-token.spomky-labs.com/)
  </Tab>
</Tabs>

## Creating Request Payloads

Here's how to encrypt your request data into a JWE token:

### Step 1: Prepare Your Data

First, construct the JSON payload with your transaction details:

```json theme={null}
{
  "activationCode": "A9X4-B7P2-Q6Z8-M3L5",
  "currency": "PHP",
  "amount": "98.00",
  "merchantReferenceNumber": "5e91bc6c-f7e2-4a39-ae0e-5e93985c94a4"
}
```

### Step 2: Encrypt into JWE Token

<CodeGroup>
  ```javascript Node.js (jose) theme={null}
  const jose = require('jose');

  // Your encryption key from Modulus Labs
  const encryptionKey = '6eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG';

  // Convert the key to the proper format
  const secretKey = Buffer.from(encryptionKey, 'base64');

  // Your payment data
  const payload = {
    activationCode: 'A9X4-B7P2-Q6Z8-M3L5',
    currency: 'PHP',
    amount: '98.00',
    merchantReferenceNumber: '5e91bc6c-f7e2-4a39-ae0e-5e93985c94a4'
  };

  // Create the JWE token
  const jwe = await new jose.CompactEncrypt(
    new TextEncoder().encode(JSON.stringify(payload))
  )
    .setProtectedHeader({ alg: 'A256KW', enc: 'A256CBC-HS512' })
    .encrypt(secretKey);

  console.log('JWE Token:', jwe);
  // Result: eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0...
  ```

  ```python Python theme={null}
  from jose import jwe
  import json

  # Your encryption key from Modulus Labs
  encryption_key = '6eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG'

  # Your payment data
  payload = {
      'activationCode': 'A9X4-B7P2-Q6Z8-M3L5',
      'currency': 'PHP',
      'amount': '98.00',
      'merchantReferenceNumber': '5e91bc6c-f7e2-4a39-ae0e-5e93985c94a4'
  }

  # Create the JWE token
  jwe_token = jwe.encrypt(
      json.dumps(payload),
      encryption_key,
      algorithm='A256KW',
      encryption='A256CBC-HS512'
  )

  print('JWE Token:', jwe_token)
  ```

  ```php PHP theme={null}
  <?php
  use Jose\Component\Core\AlgorithmManager;
  use Jose\Component\Core\JWK;
  use Jose\Component\Encryption\Algorithm\KeyEncryption\A256KW;
  use Jose\Component\Encryption\Algorithm\ContentEncryption\A256CBCHS512;
  use Jose\Component\Encryption\Compression\CompressionMethodManager;
  use Jose\Component\Encryption\JWEBuilder;
  use Jose\Component\Encryption\Serializer\CompactSerializer;

  // Your encryption key from Modulus Labs
  $encryptionKey = '6eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG';

  // Create JWK from your key
  $jwk = new JWK([
      'kty' => 'oct',
      'k' => $encryptionKey
  ]);

  // Algorithm managers
  $keyEncryptionAlgorithmManager = new AlgorithmManager([
      new A256KW(),
  ]);

  $contentEncryptionAlgorithmManager = new AlgorithmManager([
      new A256CBCHS512(),
  ]);

  // Your payment data
  $payload = json_encode([
      'activationCode' => 'A9X4-B7P2-Q6Z8-M3L5',
      'currency' => 'PHP',
      'amount' => '98.00',
      'merchantReferenceNumber' => '5e91bc6c-f7e2-4a39-ae0e-5e93985c94a4'
  ]);

  // Build the JWE
  $jweBuilder = new JWEBuilder(
      $keyEncryptionAlgorithmManager,
      $contentEncryptionAlgorithmManager,
      new CompressionMethodManager()
  );

  $jwe = $jweBuilder
      ->create()
      ->withPayload($payload)
      ->withSharedProtectedHeader([
          'alg' => 'A256KW',
          'enc' => 'A256CBC-HS512',
      ])
      ->addRecipient($jwk)
      ->build();

  // Serialize to compact format
  $serializer = new CompactSerializer();
  $token = $serializer->serialize($jwe, 0);

  echo 'JWE Token: ' . $token;
  ```

  ```csharp C# / .NET theme={null}
  using Jose;

  // Your encryption key from Modulus Labs
  var encryptionKey = "6eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG";
  var key = Base64UrlDecode(encryptionKey);

  // Base64URL decoding helper
  static byte[] Base64UrlDecode(string base64Url)
  {
      var base64 = base64Url.Replace('-', '+').Replace('_', '/');
      switch (base64.Length % 4)
      {
          case 2: base64 += "=="; break;
          case 3: base64 += "="; break;
      }
      return Convert.FromBase64String(base64);
  }

  // Your payment data
  var payload = new
  {
      activationCode = "A9X4-B7P2-Q6Z8-M3L5",
      currency = "PHP",
      amount = "98.00",
      merchantReferenceNumber = "5e91bc6c-f7e2-4a39-ae0e-5e93985c94a4"
  };

  // Create the JWE token
  var jweToken = JWT.Encode(
      payload,
      key,
      JweAlgorithm.A256KW,
      JweEncryption.A256CBC_HS512
  );

  Console.WriteLine($"JWE Token: {jweToken}");
  ```

  ```bash cURL theme={null}
  # Note: JWE encryption requires a library/tool
  # Use one of the language examples below to encrypt your payload,
  # then use the encrypted token with cURL

  ENCRYPTED_TOKEN="eyJhbGciOiJBMjU2S1ciL..."

  curl -X POST https://qrph.sbx.moduluslabs.io/v1/pay/qr \
    -u sk_YOUR_SECRET_KEY: \
    -H "Content-Type: application/json" \
    -d "{\"Token\": \"$ENCRYPTED_TOKEN\"}"
  ```

  ```go Go theme={null}
  package main

  import (
  	"encoding/base64"
  	"encoding/json"
  	"fmt"

  	"github.com/lestrrat-go/jwx/v2/jwa"
  	"github.com/lestrrat-go/jwx/v2/jwe"
  )

  func main() {
  	// Your encryption key from Modulus Labs
  	encryptionKey := "6eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG"

  	// Decode key from Base64URL
  	keyBytes, _ := base64.RawURLEncoding.DecodeString(encryptionKey)

  	// Your payment data
  	payload, _ := json.Marshal(map[string]string{
  		"activationCode":          "A9X4-B7P2-Q6Z8-M3L5",
  		"currency":                "PHP",
  		"amount":                  "98.00",
  		"merchantReferenceNumber": "5e91bc6c-f7e2-4a39-ae0e-5e93985c94a4",
  	})

  	// Create the JWE token
  	encrypted, _ := jwe.Encrypt(payload,
  		jwe.WithKey(jwa.A256KW, keyBytes),
  		jwe.WithContentEncryption(jwa.A256CBC_HS512),
  	)

  	fmt.Println("JWE Token:", string(encrypted))
  }
  ```

  ```java Java theme={null}
  import com.nimbusds.jose.*;
  import com.nimbusds.jose.crypto.AESEncrypter;
  import com.nimbusds.jose.jwk.OctetSequenceKey;
  import com.fasterxml.jackson.databind.ObjectMapper;
  import java.util.*;

  public class EncryptExample {
      public static void main(String[] args) throws Exception {
          // Your encryption key from Modulus Labs
          String encryptionKey = "6eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG";

          // Decode key from Base64URL
          byte[] keyBytes = Base64.getUrlDecoder().decode(encryptionKey);
          OctetSequenceKey jwk = new OctetSequenceKey.Builder(keyBytes).build();

          // Your payment data
          Map<String, String> payload = new LinkedHashMap<>();
          payload.put("activationCode", "A9X4-B7P2-Q6Z8-M3L5");
          payload.put("currency", "PHP");
          payload.put("amount", "98.00");
          payload.put("merchantReferenceNumber", "5e91bc6c-f7e2-4a39-ae0e-5e93985c94a4");

          String payloadJson = new ObjectMapper().writeValueAsString(payload);

          // Create the JWE token
          JWEHeader header = new JWEHeader(JWEAlgorithm.A256KW, EncryptionMethod.A256CBC_HS512);
          JWEObject jwe = new JWEObject(header, new Payload(payloadJson));
          jwe.encrypt(new AESEncrypter(jwk));

          System.out.println("JWE Token: " + jwe.serialize());
      }
  }
  ```
</CodeGroup>

### Step 3: Wrap in Request Payload

Send the JWE token in your API request:

```json theme={null}
{
  "Token": "eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0.sOoEpD55U9NMZ4JQwgFMsHGGVH0ZJvsc7Gn7LXwc8mwrFk36ordNAwJDU23S1xGQtK7ZJno3hHnvm3rhJPcXTw27ry-Lz0Gi.LDd-bawV4AhjUi9hXttE5Q.TUxl65r-0HnOBQj01ggZDMKT8pH2FDJEAKIQp_SfWXDNYZWizgZD5fmtdNxbPgj37WHFVVAvYlfWcAHYvbH-Q.p4drK620DM3qpkdVjw-xaB473Hu3hQFWpoDn_WEwYdw"
}
```

## Decrypting Response Payloads

The API returns JWE tokens in successful responses. Here's how to decrypt them:

### Example Response

```json theme={null}
{
  "Token": "eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIn0.htNErE1kLWIP0dwXcozgxLsS1bpeDIa1Qwvqdsx3MpUmyuag3ebonJbh87NrKgDjMOzzCiDwX_AefkTJtRCReYJ1rvrWmgo.ERm2rmdwPJhUncoLL6ofDA.6zqtciKiDbmx_s2AY_bRrXmedr1jafiD2HZVAxS-pWEcZo8VnpovL6epILjfTNdrITogtvCekeoZMhIuDTN6yqOlcqfl2SsblwZF5NfTMKdTUcqF8Sdx3Cg7XzT4UgLhQxd1l441E3dGNvp4coOyGkAfT5_2yVN3uGXVuz9sU.kkhQrE6cPmkOdJqZPJBa4Xphi-u2xG6y-ETcReT203Q"
}
```

### Decrypt the Token

<CodeGroup>
  ```javascript Node.js (jose) theme={null}
  const jose = require('jose');

  // Your encryption key
  const encryptionKey = '6eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG';
  const secretKey = Buffer.from(encryptionKey, 'base64');

  // The JWE token from the response
  const jweToken = response.Token;

  // Decrypt the token
  const { plaintext } = await jose.compactDecrypt(jweToken, secretKey);

  // Parse the payload
  const payload = JSON.parse(new TextDecoder().decode(plaintext));

  console.log('Decrypted payload:', payload);
  // {
  //   "id": "0ce32626-08cf-405c-adab-6d384a8871da",
  //   "qrBody": "LAawP8GKxWCwWA1gf4MVisVgsBrA+wIvFYrFYDGB9gBeLxWKxGMD6AC8Wi8ViMYD1AV4sFovFYgDrA7xYLBaLxQDWB3ixWCwWiwGsD/BisVgsFgNYH+DFYrFYLAawPsCLxWKxWAxgfYAX8VisRjA+gAvFovFYjGA9QFeLBaLxf/fXh0LAAAAAAzytx7GnpKIgYABYCBgABgIGAAGAgaAgYABYCBgABgIGAAGAgaAgYABYBC6Qa/HfkoA6gAAAABJRU5ErkJggg=="
  // }
  ```

  ```python Python theme={null}
  from jose import jwe
  import json

  # Your encryption key
  encryption_key = '6eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG'

  # The JWE token from the response
  jwe_token = response['Token']

  # Decrypt the token
  decrypted_data = jwe.decrypt(jwe_token, encryption_key)

  # Parse the payload
  payload = json.loads(decrypted_data)

  print('Decrypted payload:', payload)
  ```

  ```php PHP theme={null}
  <?php
  // Decrypt using the same setup as encryption
  $decrypted = $jweLoader->loadAndDecryptWithKey(
      $jweToken,
      $jwk,
      $recipient
  );

  // Get the payload
  $payload = $decrypted->getPayload();
  $data = json_decode($payload, true);

  print_r($data);
  ```

  ```csharp C# / .NET theme={null}
  using Jose;

  // Your encryption key
  var encryptionKey = "6eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG";
  var key = Base64UrlDecode(encryptionKey);

  // The JWE token from the response
  var jweToken = response.Token;

  // Decrypt the token
  var decryptedJson = JWT.Decode(jweToken, key);
  var payload = JsonConvert.DeserializeObject<dynamic>(decryptedJson);

  Console.WriteLine($"Transaction ID: {payload.id}");
  Console.WriteLine($"QR Body: {payload.qrBody}");
  ```

  ```bash cURL theme={null}
  # Decryption requires a library/tool
  # Use one of the language examples to decrypt the JWE response token
  # The token from the response body:
  echo "Use Node.js, Python, PHP, Go, Java, or C# to decrypt the response Token"
  ```

  ```go Go theme={null}
  package main

  import (
  	"encoding/base64"
  	"encoding/json"
  	"fmt"

  	"github.com/lestrrat-go/jwx/v2/jwa"
  	"github.com/lestrrat-go/jwx/v2/jwe"
  )

  func main() {
  	encryptionKey := "6eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG"
  	keyBytes, _ := base64.RawURLEncoding.DecodeString(encryptionKey)

  	// The JWE token from the response
  	jweToken := "eyJhbGciOiJBMjU2S1ciL..." // response.Token

  	// Decrypt the token
  	decrypted, _ := jwe.Decrypt([]byte(jweToken), jwe.WithKey(jwa.A256KW, keyBytes))

  	// Parse the payload
  	var payload map[string]interface{}
  	json.Unmarshal(decrypted, &payload)

  	fmt.Printf("Transaction ID: %s\n", payload["id"])
  	fmt.Printf("QR Body: %s\n", payload["qrBody"])
  }
  ```

  ```java Java theme={null}
  import com.nimbusds.jose.*;
  import com.nimbusds.jose.crypto.AESDecrypter;
  import com.nimbusds.jose.jwk.OctetSequenceKey;
  import com.fasterxml.jackson.databind.ObjectMapper;
  import java.util.*;

  public class DecryptExample {
      public static void main(String[] args) throws Exception {
          String encryptionKey = "6eaNv7t5xyCuiBfGCq2q7wu9uHEH3mTQ1Mq0c53XO1c53vfG";
          byte[] keyBytes = Base64.getUrlDecoder().decode(encryptionKey);
          OctetSequenceKey jwk = new OctetSequenceKey.Builder(keyBytes).build();

          // The JWE token from the response
          String jweToken = "eyJhbGciOiJBMjU2S1ciL..."; // response.getToken()

          // Decrypt the token
          JWEObject jweObject = JWEObject.parse(jweToken);
          jweObject.decrypt(new AESDecrypter(jwk));
          String decryptedJson = jweObject.getPayload().toString();

          Map<String, String> payload = new ObjectMapper().readValue(decryptedJson, Map.class);

          System.out.println("Transaction ID: " + payload.get("id"));
          System.out.println("QR Body: " + payload.get("qrBody"));
      }
  }
  ```
</CodeGroup>

## Response Types

The API returns different response formats based on the request status:

<Tabs>
  <Tab title="Success">
    ### Successful Requests

    Returns a JWE token containing the response data:

    ```json theme={null}
    {
      "Token": "eyJhbGciOiJBMjU2S1ciL..."
    }
    ```

    **Decrypted payload:**

    ```json theme={null}
    {
      "id": "0ce32626-08cf-405c-adab-6d384a8871da",
      "qrBody": "LAawP8GKxWCwWA1gf4MVisVgs..."
    }
    ```
  </Tab>

  <Tab title="Declined">
    ### Declined Requests

    Returns a JWE token containing the error object:

    ```json theme={null}
    {
      "Token": "eyJhbGciOiJBMjU2S1ciL..."
    }
    ```

    **Decrypted payload:**

    ```json theme={null}
    {
      "code": "10000002",
      "error": "Account is disabled. Please contact support for assistance.",
      "referenceNumber": "338e2710-8268-4afe-8ef9-9765b0b74688"
    }
    ```
  </Tab>

  <Tab title="Unauthorized">
    ### Unauthorized Requests

    Returns the error object directly (not encrypted):

    ```json theme={null}
    {
      "code": "10000002",
      "error": "Account is disabled. Please contact support for assistance.",
      "referenceNumber": "338e2710-8268-4afe-8ef9-9765b0b74688"
    }
    ```

    <Info>
      Authentication errors bypass encryption since the credentials are invalid.
    </Info>
  </Tab>
</Tabs>

## Common Issues & Solutions

<AccordionGroup>
  <Accordion title="Invalid JWE Token Error">
    **Cause:** Mismatch in encryption algorithms or incorrect key

    **Solution:**

    * Verify you're using `A256KW` for key wrap
    * Verify you're using `A256CBC-HS512` for content encryption
    * Check that your encryption key is correct
    * Ensure the key is Base64-decoded to raw bytes
  </Accordion>

  <Accordion title="Decryption Fails">
    **Cause:** Token has been modified or key mismatch

    **Solution:**

    * Ensure the token hasn't been modified during transit
    * Verify you're using the same encryption key for encryption and decryption
    * Check that the token is complete (not truncated)
  </Accordion>

  <Accordion title="Library Compatibility Issues">
    **Cause:** Not all JWT libraries support JWE

    **Solution:**

    * Use the recommended libraries listed above
    * Ensure your library supports both `A256KW` and `A256CBC-HS512`
    * Update to the latest version of your chosen library
  </Accordion>

  <Accordion title="Base64 Encoding Issues">
    **Cause:** Incorrect encoding of binary data

    **Solution:**

    * Use URL-safe Base64 encoding (no padding)
    * Ensure consistent encoding between encryption and decryption
    * Use library-provided encoding functions
  </Accordion>
</AccordionGroup>

## Security Best Practices

<CardGroup cols={2}>
  <Card title="Key Storage" icon="vault">
    Store encryption keys in secure vaults or environment variables, never in code
  </Card>

  <Card title="Key Rotation" icon="arrows-rotate">
    Implement a key rotation strategy for enhanced security
  </Card>

  <Card title="Validate Tokens" icon="check">
    Always validate token structure and algorithms before decryption
  </Card>

  <Card title="Monitor Failures" icon="bell">
    Log and monitor decryption failures for potential security issues
  </Card>
</CardGroup>

## Complete Example

Here's a complete end-to-end example:

<CodeGroup>
  ```javascript Node.js theme={null}
  const jose = require('jose');
  const axios = require('axios');

  const SECRET_KEY = process.env.MODULUS_SECRET_KEY;
  const ENCRYPTION_KEY = process.env.MODULUS_ENCRYPTION_KEY;

  async function createDynamicQR() {
    // 1. Prepare payload
    const payload = {
      activationCode: 'A9X4-B7P2-Q6Z8-M3L5',
      currency: 'PHP',
      amount: '98.00',
      merchantReferenceNumber: crypto.randomUUID()
    };

    // 2. Encrypt payload
    const secretKey = Buffer.from(ENCRYPTION_KEY, 'base64');
    const jweToken = await new jose.CompactEncrypt(
      new TextEncoder().encode(JSON.stringify(payload))
    )
      .setProtectedHeader({ alg: 'A256KW', enc: 'A256CBC-HS512' })
      .encrypt(secretKey);

    // 3. Make API request
    const response = await axios.post(
      'https://qrph.sbx.moduluslabs.io/v1/pay/qr',
      { Token: jweToken },
      {
        auth: { username: SECRET_KEY, password: '' },
        headers: { 'Content-Type': 'application/json' }
      }
    );

    // 4. Decrypt response
    const { plaintext } = await jose.compactDecrypt(
      response.data.Token,
      secretKey
    );
    const result = JSON.parse(new TextDecoder().decode(plaintext));

    console.log('Transaction ID:', result.id);
    console.log('QR Body:', result.qrBody);

    return result;
  }

  createDynamicQR().catch(console.error);
  ```

  ```python Python theme={null}
  import os
  import json
  import requests
  from jose import jwe
  from uuid import uuid4

  SECRET_KEY = os.getenv('MODULUS_SECRET_KEY')
  ENCRYPTION_KEY = os.getenv('MODULUS_ENCRYPTION_KEY')

  def create_dynamic_qr():
      # 1. Prepare payload
      payload = {
          'activationCode': 'A9X4-B7P2-Q6Z8-M3L5',
          'currency': 'PHP',
          'amount': '98.00',
          'merchantReferenceNumber': str(uuid4())
      }

      # 2. Encrypt payload
      jwe_token = jwe.encrypt(
          json.dumps(payload),
          ENCRYPTION_KEY,
          algorithm='A256KW',
          encryption='A256CBC-HS512'
      )

      # 3. Make API request
      response = requests.post(
          'https://qrph.sbx.moduluslabs.io/v1/pay/qr',
          json={'Token': jwe_token},
          auth=(SECRET_KEY, ''),
          headers={'Content-Type': 'application/json'}
      )

      # 4. Decrypt response
      decrypted_data = jwe.decrypt(response.json()['Token'], ENCRYPTION_KEY)
      result = json.loads(decrypted_data)

      print(f"Transaction ID: {result['id']}")
      print(f"QR Body: {result['qrBody']}")

      return result

  if __name__ == '__main__':
      create_dynamic_qr()
  ```

  ```bash cURL theme={null}
  # Complete flow requires a language with JWE support for encryption/decryption
  # Use cURL only for the HTTP request step:

  ENCRYPTED_TOKEN="eyJhbGciOiJBMjU2S1ciL..."

  curl -X POST https://qrph.sbx.moduluslabs.io/v1/pay/qr \
    -u $MODULUS_SECRET_KEY: \
    -H "Content-Type: application/json" \
    -d "{\"Token\": \"$ENCRYPTED_TOKEN\"}"

  # Decrypt the response Token using your preferred language
  ```

  ```php PHP theme={null}
  <?php
  require 'vendor/autoload.php';

  use Jose\Component\Core\AlgorithmManager;
  use Jose\Component\Core\JWK;
  use Jose\Component\Encryption\Algorithm\KeyEncryption\A256KW;
  use Jose\Component\Encryption\Algorithm\ContentEncryption\A256CBCHS512;
  use Jose\Component\Encryption\Compression\CompressionMethodManager;
  use Jose\Component\Encryption\JWEBuilder;
  use Jose\Component\Encryption\JWEDecrypter;
  use Jose\Component\Encryption\Serializer\CompactSerializer;

  $SECRET_KEY = getenv('MODULUS_SECRET_KEY');
  $ENCRYPTION_KEY = getenv('MODULUS_ENCRYPTION_KEY');

  function createDynamicQR() {
      global $SECRET_KEY, $ENCRYPTION_KEY;

      // 1. Prepare payload
      $payload = json_encode([
          'activationCode' => 'A9X4-B7P2-Q6Z8-M3L5',
          'currency' => 'PHP',
          'amount' => '98.00',
          'merchantReferenceNumber' => uniqid('', true)
      ]);

      // 2. Encrypt payload
      $jwk = new JWK(['kty' => 'oct', 'k' => $ENCRYPTION_KEY]);

      $keyAlgorithmManager = new AlgorithmManager([new A256KW()]);
      $contentAlgorithmManager = new AlgorithmManager([new A256CBCHS512()]);

      $jweBuilder = new JWEBuilder(
          $keyAlgorithmManager,
          $contentAlgorithmManager,
          new CompressionMethodManager()
      );

      $jwe = $jweBuilder->create()
          ->withPayload($payload)
          ->withSharedProtectedHeader(['alg' => 'A256KW', 'enc' => 'A256CBC-HS512'])
          ->addRecipient($jwk)
          ->build();

      $serializer = new CompactSerializer();
      $jweToken = $serializer->serialize($jwe, 0);

      // 3. Make API request
      $ch = curl_init('https://qrph.sbx.moduluslabs.io/v1/pay/qr');
      curl_setopt($ch, CURLOPT_POST, 1);
      curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['Token' => $jweToken]));
      curl_setopt($ch, CURLOPT_USERPWD, $SECRET_KEY . ':');
      curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

      $response = curl_exec($ch);
      curl_close($ch);

      // 4. Decrypt response
      $responseData = json_decode($response, true);
      $jweDecrypter = new JWEDecrypter(
          $keyAlgorithmManager,
          $contentAlgorithmManager,
          null
      );

      $loadedJwe = $serializer->unserialize($responseData['Token']);
      $jweDecrypter->decryptUsingKey($loadedJwe, $jwk, 0);
      $result = json_decode($loadedJwe->getPayload(), true);

      echo "Transaction ID: {$result['id']}\n";
      echo "QR Body: " . substr($result['qrBody'], 0, 50) . "...\n";

      return $result;
  }

  createDynamicQR();
  ```

  ```go Go theme={null}
  package main

  import (
  	"bytes"
  	"encoding/base64"
  	"encoding/json"
  	"fmt"
  	"io"
  	"net/http"
  	"os"

  	"github.com/lestrrat-go/jwx/v2/jwa"
  	"github.com/lestrrat-go/jwx/v2/jwe"
  )

  func main() {
  	secretKey := os.Getenv("MODULUS_SECRET_KEY")
  	encryptionKey := os.Getenv("MODULUS_ENCRYPTION_KEY")

  	// 1. Prepare payload
  	payload, _ := json.Marshal(map[string]string{
  		"activationCode":          "A9X4-B7P2-Q6Z8-M3L5",
  		"currency":                "PHP",
  		"amount":                  "98.00",
  		"merchantReferenceNumber": "5e91bc6c-f7e2-4a39-ae0e-5e93985c94a4",
  	})

  	// 2. Encrypt payload
  	keyBytes, _ := base64.RawURLEncoding.DecodeString(encryptionKey)
  	encrypted, _ := jwe.Encrypt(payload,
  		jwe.WithKey(jwa.A256KW, keyBytes),
  		jwe.WithContentEncryption(jwa.A256CBC_HS512),
  	)

  	// 3. Make API request
  	reqBody, _ := json.Marshal(map[string]string{"Token": string(encrypted)})
  	req, _ := http.NewRequest("POST", "https://qrph.sbx.moduluslabs.io/v1/pay/qr", bytes.NewBuffer(reqBody))
  	req.SetBasicAuth(secretKey, "")
  	req.Header.Set("Content-Type", "application/json")

  	resp, _ := (&http.Client{}).Do(req)
  	defer resp.Body.Close()
  	body, _ := io.ReadAll(resp.Body)

  	// 4. Decrypt response
  	var tokenResp map[string]string
  	json.Unmarshal(body, &tokenResp)

  	decrypted, _ := jwe.Decrypt([]byte(tokenResp["Token"]), jwe.WithKey(jwa.A256KW, keyBytes))

  	var result map[string]string
  	json.Unmarshal(decrypted, &result)

  	fmt.Printf("Transaction ID: %s\n", result["id"])
  	fmt.Printf("QR Body: %s...\n", result["qrBody"][:50])
  }
  ```

  ```java Java theme={null}
  import com.nimbusds.jose.*;
  import com.nimbusds.jose.crypto.*;
  import com.nimbusds.jose.jwk.OctetSequenceKey;
  import com.fasterxml.jackson.databind.ObjectMapper;
  import java.net.URI;
  import java.net.http.*;
  import java.util.*;

  public class CompleteExample {
      public static void main(String[] args) throws Exception {
          String secretKey = System.getenv("MODULUS_SECRET_KEY");
          String encryptionKey = System.getenv("MODULUS_ENCRYPTION_KEY");
          ObjectMapper mapper = new ObjectMapper();

          // 1. Prepare payload
          Map<String, String> payload = new LinkedHashMap<>();
          payload.put("activationCode", "A9X4-B7P2-Q6Z8-M3L5");
          payload.put("currency", "PHP");
          payload.put("amount", "98.00");
          payload.put("merchantReferenceNumber", UUID.randomUUID().toString());

          // 2. Encrypt payload
          byte[] keyBytes = Base64.getUrlDecoder().decode(encryptionKey);
          OctetSequenceKey jwk = new OctetSequenceKey.Builder(keyBytes).build();

          JWEHeader header = new JWEHeader(JWEAlgorithm.A256KW, EncryptionMethod.A256CBC_HS512);
          JWEObject jwe = new JWEObject(header, new Payload(mapper.writeValueAsString(payload)));
          jwe.encrypt(new AESEncrypter(jwk));

          // 3. Make API request
          HttpClient client = HttpClient.newHttpClient();
          String auth = Base64.getEncoder().encodeToString((secretKey + ":").getBytes());

          HttpRequest request = HttpRequest.newBuilder()
              .uri(URI.create("https://qrph.sbx.moduluslabs.io/v1/pay/qr"))
              .header("Authorization", "Basic " + auth)
              .header("Content-Type", "application/json")
              .POST(HttpRequest.BodyPublishers.ofString(
                  mapper.writeValueAsString(Map.of("Token", jwe.serialize()))
              ))
              .build();

          HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

          // 4. Decrypt response
          Map<String, String> responseData = mapper.readValue(response.body(), Map.class);
          JWEObject responseJwe = JWEObject.parse(responseData.get("Token"));
          responseJwe.decrypt(new AESDecrypter(jwk));

          Map<String, String> result = mapper.readValue(responseJwe.getPayload().toString(), Map.class);
          System.out.println("Transaction ID: " + result.get("id"));
          System.out.println("QR Body: " + result.get("qrBody").substring(0, 50) + "...");
      }
  }
  ```

  ```csharp C# / .NET theme={null}
  using System.Net.Http.Headers;
  using System.Text;
  using System.Text.Json;
  using Jose;

  var secretKey = Environment.GetEnvironmentVariable("MODULUS_SECRET_KEY");
  var encryptionKey = Environment.GetEnvironmentVariable("MODULUS_ENCRYPTION_KEY");

  // Base64URL decode helper
  static byte[] Base64UrlDecode(string base64Url)
  {
      var base64 = base64Url.Replace('-', '+').Replace('_', '/');
      switch (base64.Length % 4)
      {
          case 2: base64 += "=="; break;
          case 3: base64 += "="; break;
      }
      return Convert.FromBase64String(base64);
  }

  // 1. Prepare payload
  var payload = new
  {
      activationCode = "A9X4-B7P2-Q6Z8-M3L5",
      currency = "PHP",
      amount = "98.00",
      merchantReferenceNumber = Guid.NewGuid().ToString()
  };

  // 2. Encrypt payload
  var key = Base64UrlDecode(encryptionKey);
  var jweToken = JWT.Encode(
      JsonSerializer.Serialize(payload),
      key,
      JweAlgorithm.A256KW,
      JweEncryption.A256CBC_HS512
  );

  // 3. Make API request
  using var client = new HttpClient();
  var authBytes = Encoding.ASCII.GetBytes($"{secretKey}:");
  client.DefaultRequestHeaders.Authorization =
      new AuthenticationHeaderValue("Basic", Convert.ToBase64String(authBytes));

  var content = new StringContent(
      JsonSerializer.Serialize(new { Token = jweToken }),
      Encoding.UTF8,
      "application/json"
  );

  var response = await client.PostAsync(
      "https://qrph.sbx.moduluslabs.io/v1/pay/qr", content
  );
  var responseBody = await response.Content.ReadAsStringAsync();

  // 4. Decrypt response
  var responseData = JsonSerializer.Deserialize<JsonElement>(responseBody);
  var responseToken = responseData.GetProperty("Token").GetString();
  var decryptedJson = JWT.Decode(responseToken, key);
  var result = JsonSerializer.Deserialize<JsonElement>(decryptedJson);

  Console.WriteLine($"Transaction ID: {result.GetProperty("id")}");
  Console.WriteLine($"QR Body: {result.GetProperty("qrBody").GetString()?[..50]}...");
  ```
</CodeGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Quickstart Guide" icon="rocket" href="/docs/qr/quickstart">
    Follow a complete example with encryption
  </Card>

  <Card title="Create QR Endpoint" icon="qrcode" href="/api-reference/qr/create">
    See the full API reference
  </Card>

  <Card title="Error Handling" icon="triangle-exclamation" href="/docs/errors">
    Learn how to handle encrypted error responses
  </Card>

  <Card title="Testing" icon="flask" href="/docs/qr/testing">
    Test encryption in the sandbox environment
  </Card>
</CardGroup>
