---
updatedAt: 2026-06-11T16:01:12.000Z
---

Fetch the complete documentation index at: https://simpay-prod.readme.io/llms.txt. Use this file to discover all available pages before exploring further. Append .md to any documentation page URL to get its markdown version.

# HMAC Documentation

Complete guide for implementing HMAC-SHA512 signatures in multiple languages

# HMAC Documentation

## Summary

After obtaining your HMAC key, this documentation provides comprehensive instructions for generating HMAC (Hash-based Message Authentication Code) signatures using various programming languages. HMAC is **required** for utilizing the PIX Cash In and PIX Cash Out endpoints, ensuring data integrity and authenticity in HTTP requests.

HMAC authentication is a robust method to safeguard your API endpoints. It ensures data integrity and restricts access to authorized clients only. By implementing HMAC authentication, you can enhance the security of your API, confidently share your services globally, and keep malicious actors at bay.

> 🔒 **Security:** Properly configuring a script that formats the JSON payload correctly is **essential** for consistently generating HMACs.

## How HMAC Works

```
Request Body (JSON) 
    ↓
Normalize JSON (remove spaces)
    ↓
Generate HMAC-SHA512 Hash with Secret Key
    ↓
Convert to Hexadecimal
    ↓
Include in Request Headers/Body
```

## Quick Start

### Basic Steps

1. **Prepare the Request Body**
   * Serialize to JSON without pretty-printing
   * Remove spaces after `:` and `,` characters
   * Example: `{"key":"value","number":123}` ✅
   * Not: `{"key": "value", "number": 123}` ❌

2. **Generate HMAC Signature**
   * Use HMAC-SHA512 algorithm
   * Use your secret `hmac_key` provided during registration
   * Output in hexadecimal format

3. **Include in Request**
   * Add signature to request headers or body (check endpoint documentation)

## Script Functionality

The HMAC generation process can be broken down into the following steps:

### 1. Import Cryptographic Library

Import the cryptographic library for your programming language.

### 2. Create `generateHMAC` Function

This function takes two parameters:

* `jsonData`: The request body in JSON format
* `secretKey`: The secret key (HMAC key) used to generate the HMAC

The function uses HMAC-SHA512 to generate the signature and returns the result in hexadecimal format.

### 3. Retrieve the Request Body

Get the request body as a raw string.

### 4. Parse the JSON

Convert the raw JSON string into a native object/dictionary.

### 5. Convert Back to JSON String

Convert the object back to a JSON string **without formatting** (no indentation, no pretty-printing).

### 6. Remove Unnecessary Spaces

**Critical Step:** Remove spaces after colons (`:`) and commas (`,`) in the JSON string. This ensures the HMAC is generated consistently, regardless of the original JSON formatting.

```
Before: {"key": "value", "number": 123}
After:  {"key":"value","number":123}
```

### 7. Retrieve the Secret Key

Use the HMAC key provided to you during the registration process.

> 📧 **Note:** Only after registering the HMAC key will it be possible to complete this step.

**Example key:** `edcb3xxxxf248b744653f052b22cexxxx8d87ad2b2777xxxx35f33d27be6xxxx`

#### Best Practice: Secure Key Storage

**Never** include the secret key directly in your code. Retrieve it from a secure source such as environment variables or a secret management system.

### 8. Generate the HMAC

Call the `generateHMAC` function with the formatted request body and secret key, storing the generated HMAC in a variable.

### 9. Store or Use the HMAC

Store the generated HMAC in a variable for use in API requests, or log it for debugging purposes.

## Complete Implementation Examples

### JavaScript (Postman)

```javascript
// Function to generate HMAC
function generateHMAC(jsonData, secretKey) {
    const crypto = require('crypto-js');
    const hmacSHA512 = crypto.HmacSHA512(jsonData, secretKey);
    return hmacSHA512.toString(crypto.enc.Hex);
}

// Get the request body
let payload = pm.request.body.raw;

// Parse the JSON string
let jsonObj = JSON.parse(payload);

// Convert back to a JSON string without pretty-printing
payload = JSON.stringify(jsonObj);

// Replace ": " with ":" and ", " with ","
payload = payload.replace(/:\s/g, ':').replace(/,\s/g, ',');

// Get the secret key (you need to set this in your environment variables)
const secretKey = "edcb3xxxxf248b744653f052b22cexxxx8d87ad2b2777xxxx35f33d27be6xxxx";
// Best practice: const secretKey = pm.environment.get('hmac_key');

// Generate the HMAC
const hmac = generateHMAC(payload, secretKey);

// Set the HMAC in an environment variable for later use
pm.collectionVariables.set('generated_hmac', hmac);

console.log('Generated HMAC:', hmac);
```

**Postman Environment Variables Setup:**

```javascript
// Get the secret key from Postman environment variables
const secretKey = pm.environment.get('hmac_key');

// In Postman, it is a best practice to store sensitive information like 
// secret keys in environment variables. You can set these variables in the 
// Postman interface and retrieve them securely in your scripts.
```

***

### Python

```python
import hashlib
import hmac
import json


def gera_hash(json_data, chave_secreta):
    """Generate HMAC-SHA512 hash for API request authentication."""
    chave_secreta = chave_secreta.encode('utf-8')
    hmac_sha512 = hmac.new(chave_secreta, json_data, hashlib.sha512)
    chave_hmac = hmac_sha512.hexdigest()
    return chave_hmac


# Get the request body (assuming it's a JSON string)
payload = '{"key1": "value1", "key2": "value2"}'

# Normalize JSON formatting
payload_json_str = json.dumps(json.loads(payload), ensure_ascii=False, separators=(',', ':'))
payload_json_str = payload_json_str.encode('utf-8')

# Secret key (use environment variable in production)
secret_key = "7a3edd380d2356bcb5f4bb1ff3a25f918cfb11e83c2eb468f967457037e43949"
# Best practice: secret_key = os.getenv('HMAC_KEY')

# Generate HMAC
hmac_result = gera_hash(payload_json_str, secret_key)
print("Generated HMAC:", hmac_result)
```

**Best Practice - Using Environment Variables:**

```python
import os
import hmac
import hashlib
import json


def generate_hmac(json_data, secret_key):
    """Generate HMAC-SHA512 hash."""
    secret_bytes = secret_key.encode('utf-8')
    hmac_hash = hmac.new(secret_bytes, json_data, hashlib.sha512)
    return hmac_hash.hexdigest()


# Load secret key from environment
secret_key = os.getenv('HMAC_KEY')
if not secret_key:
    raise ValueError("HMAC_KEY environment variable not set")

# Prepare payload
payload = {"key1": "value1", "key2": "value2"}
payload_str = json.dumps(payload, ensure_ascii=False, separators=(',', ':'))
payload_bytes = payload_str.encode('utf-8')

# Generate HMAC
hmac_signature = generate_hmac(payload_bytes, secret_key)
print(f"Generated HMAC: {hmac_signature}")
```

***

### Java

```java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Formatter;

public class HMACGenerator {

    public static String generateHMAC(String jsonData, String secretKey) throws Exception {
        Mac sha512_HMAC = Mac.getInstance("HmacSHA512");
        SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA512");
        sha512_HMAC.init(keySpec);
        
        byte[] hmacBytes = sha512_HMAC.doFinal(jsonData.getBytes(StandardCharsets.UTF_8));
        
        return bytesToHex(hmacBytes);
    }

    private static String bytesToHex(byte[] bytes) {
        Formatter formatter = new Formatter();
        for (byte b : bytes) {
            formatter.format("%02x", b);
        }
        return formatter.toString();
    }

    public static void main(String[] args) throws Exception {
        // Payload (already normalized)
        String payload = "{\"key1\":\"value1\",\"key2\":\"value2\"}";

        // Secret key (use environment variable in production)
        String secretKey = "edcb3xxxxf248b744653f052b22cexxxx8d87ad2b2777xxxx35f33d27be6xxxx";
        // Best practice: String secretKey = System.getenv("HMAC_KEY");

        // Generate the HMAC
        String hmacResult = generateHMAC(payload, secretKey);

        System.out.println("Generated HMAC: " + hmacResult);
    }
}
```

**Best Practice - Using Environment Variables:**

```java
public class SecureHMACGenerator {
    
    public static void main(String[] args) throws Exception {
        // Load secret key from environment
        String secretKey = System.getenv("HMAC_KEY");
        if (secretKey == null || secretKey.isEmpty()) {
            throw new IllegalStateException("HMAC_KEY environment variable not set");
        }
        
        // Prepare payload
        String payload = "{\"key1\":\"value1\",\"key2\":\"value2\"}";
        
        // Generate HMAC
        String hmacSignature = generateHMAC(payload, secretKey);
        System.out.println("Generated HMAC: " + hmacSignature);
    }
    
    // generateHMAC method same as above
}
```

***

### JavaScript (Node.js)

```javascript
const crypto = require('crypto');

function generateHMAC(jsonData, secretKey) {
    const hmac = crypto.createHmac('sha512', secretKey);
    hmac.update(jsonData);
    return hmac.digest('hex');
}

// Get the request body
let payload = '{"key1": "value1", "key2": "value2"}';

// Parse the JSON string
let jsonObj = JSON.parse(payload);

// Convert back to a JSON string without pretty-printing
payload = JSON.stringify(jsonObj);

// Replace ": " with ":" and ", " with ","
payload = payload.replace(/:\s/g, ':').replace(/,\s/g, ',');

// Secret key (use environment variable in production)
const secretKey = "edcb3xxxxf248b744653f052b22cexxxx8d87ad2b2777xxxx35f33d27be6xxxx";
// Best practice: const secretKey = process.env.HMAC_KEY;

// Generate the HMAC
const hmac = generateHMAC(payload, secretKey);

console.log('Generated HMAC:', hmac);
```

**Best Practice - Environment Variables & Error Handling:**

```javascript
require('dotenv').config();  // Load .env file
const crypto = require('crypto');

function generateHMAC(jsonData, secretKey) {
    if (!secretKey) {
        throw new Error('HMAC_KEY not configured');
    }
    
    const hmac = crypto.createHmac('sha512', secretKey);
    hmac.update(jsonData);
    return hmac.digest('hex');
}

function normalizeJSON(payload) {
    // Parse and stringify to normalize
    const jsonObj = JSON.parse(payload);
    const normalized = JSON.stringify(jsonObj);
    // Remove spaces after : and ,
    return normalized.replace(/:\s/g, ':').replace(/,\s/g, ',');
}

// Load secret from environment
const secretKey = process.env.HMAC_KEY;

if (!secretKey) {
    throw new Error('HMAC_KEY environment variable is not set');
}

// Example usage
const payload = {"key1": "value1", "key2": "value2"};
const payloadStr = normalizeJSON(JSON.stringify(payload));

const hmacSignature = generateHMAC(payloadStr, secretKey);
console.log('Generated HMAC:', hmacSignature);

module.exports = { generateHMAC, normalizeJSON };
```

***

### C\#

```csharp
using System;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

class Program
{
    static void Main()
    {
        string payload = "{\"key1\":\"value1\",\"key2\":\"value2\"}";

        // Parse the JSON string
        JObject jsonObj = JObject.Parse(payload);

        // Convert back to a JSON string without pretty-printing
        payload = JsonConvert.SerializeObject(jsonObj, Formatting.None);

        // Secret key (use environment variable in production)
        string secretKey = "edcb3xxxxf248b744653f052b22cexxxx8d87ad2b2777xxxx35f33d27be6xxxx";
        // Best practice: string secretKey = Environment.GetEnvironmentVariable("HMAC_KEY");

        // Generate the HMAC
        string hmac = GenerateHMAC(payload, secretKey);

        Console.WriteLine("Generated HMAC: " + hmac);
    }

    static string GenerateHMAC(string jsonData, string secretKey)
    {
        using (var hmacsha512 = new HMACSHA512(Encoding.UTF8.GetBytes(secretKey)))
        {
            byte[] hashmessage = hmacsha512.ComputeHash(Encoding.UTF8.GetBytes(jsonData));
            return BitConverter.ToString(hashmessage).Replace("-", "").ToLower();
        }
    }
}
```

**Best Practice - Environment Variables & Error Handling:**

```csharp
using System;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class SecureHMACGenerator
{
    public static string GenerateHMAC(string jsonData, string secretKey)
    {
        if (string.IsNullOrEmpty(secretKey))
        {
            throw new ArgumentException("Secret key cannot be null or empty", nameof(secretKey));
        }

        using (var hmacsha512 = new HMACSHA512(Encoding.UTF8.GetBytes(secretKey)))
        {
            byte[] hashmessage = hmacsha512.ComputeHash(Encoding.UTF8.GetBytes(jsonData));
            return BitConverter.ToString(hashmessage).Replace("-", "").ToLower();
        }
    }

    static void Main()
    {
        // Load secret key from environment
        string secretKey = Environment.GetEnvironmentVariable("HMAC_KEY");
        if (string.IsNullOrEmpty(secretKey))
        {
            throw new InvalidOperationException("HMAC_KEY environment variable not set");
        }

        // Prepare payload
        var payload = new { key1 = "value1", key2 = "value2" };
        string payloadStr = JsonConvert.SerializeObject(payload, Formatting.None);

        // Generate HMAC
        string hmacSignature = GenerateHMAC(payloadStr, secretKey);
        Console.WriteLine($"Generated HMAC: {hmacSignature}");
    }
}
```

***

### PHP

```php
<?php

function generateHMAC($jsonData, $secretKey) {
    return hash_hmac('sha512', $jsonData, $secretKey);
}

// Get the request body
$payload = '{"key1":"value1","key2":"value2"}';

// Decode and encode JSON to remove pretty-printing
$jsonObj = json_decode($payload, true);
$payload = json_encode($jsonObj, JSON_UNESCAPED_SLASHES);

// Secret key (use environment variable in production)
$secretKey = "edcb3xxxxf248b744653f052b22cexxxx8d87ad2b2777xxxx35f33d27be6xxxx";
// Best practice: $secretKey = getenv('HMAC_KEY');

// Generate the HMAC
$hmac = generateHMAC($payload, $secretKey);

echo "Generated HMAC: " . $hmac;
?>
```

**Best Practice - Environment Variables & Error Handling:**

```php
<?php

function generateHMAC($jsonData, $secretKey) {
    if (empty($secretKey)) {
        throw new Exception('Secret key is required');
    }
    return hash_hmac('sha512', $jsonData, $secretKey);
}

function normalizeJSON($payload) {
    // Decode and encode to normalize
    $jsonObj = json_decode($payload, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
        throw new Exception('Invalid JSON: ' . json_last_error_msg());
    }
    return json_encode($jsonObj, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}

// Load secret key from environment
$secretKey = getenv('HMAC_KEY');

if ($secretKey === false || empty($secretKey)) {
    throw new Exception('HMAC_KEY environment variable not set');
}

// Example usage
$payload = ['key1' => 'value1', 'key2' => 'value2'];
$payloadStr = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

$hmacSignature = generateHMAC($payloadStr, $secretKey);
echo "Generated HMAC: " . $hmacSignature . "\n";
?>
```

## Common Issues and Solutions

### Issue 1: HMAC Signature Mismatch

**Symptom:** API returns `403 Forbidden` with "Invalid HMAC signature" error.

**Causes & Solutions:**

1. **Spaces in JSON:**
   ```javascript
   // ❌ Wrong
   {"key": "value", "number": 123}

   // ✅ Correct
   {"key":"value","number":123}
   ```
   **Solution:** Use `.replace(/:\s/g, ':').replace(/,\s/g, ',')`

2. **Pretty-printed JSON:**
   ```javascript
   // ❌ Wrong
   {
     "key": "value"
   }

   // ✅ Correct
   {"key":"value"}
   ```
   **Solution:** Use `JSON.stringify()` without formatting options

3. **Wrong Algorithm:**
   * Must use **HMAC-SHA512**, not SHA256 or other algorithms

4. **Wrong Secret Key:**
   * Verify you're using the correct `hmac_key`
   * Check for trailing spaces or hidden characters

5. **Request Body Modified:**
   * Ensure the request body sent to API matches the signed payload exactly

### Issue 2: Environment Variable Not Loaded

**Symptom:** Application crashes with "undefined" or "null" secret key error.

**Solutions:**

**Node.js:**

```javascript
require('dotenv').config();
const secretKey = process.env.HMAC_KEY;
if (!secretKey) throw new Error('HMAC_KEY not set');
```

**Python:**

```python
import os
from dotenv import load_dotenv

load_dotenv()
secret_key = os.getenv('HMAC_KEY')
if not secret_key:
    raise ValueError('HMAC_KEY not set')
```

**PHP:**

```php
$secretKey = getenv('HMAC_KEY');
if (!$secretKey) {
    throw new Exception('HMAC_KEY environment variable not set');
}
```

### Issue 3: Unicode and Special Characters

**Symptom:** HMAC works for simple requests but fails with special characters.

**Solution:** Ensure proper encoding:

**Python:**

```python
# Use ensure_ascii=False for Unicode support
payload_str = json.dumps(payload, ensure_ascii=False, separators=(',', ':'))
```

**PHP:**

```php
// Use JSON_UNESCAPED_UNICODE
$payload = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
```

**JavaScript:**

```javascript
// JSON.stringify handles Unicode correctly by default
const payload = JSON.stringify(data);
```

## Testing Your Implementation

### Test Payload

```json
{
  "amount": 100.50,
  "description": "Test payment",
  "customer_id": "12345"
}
```

### Expected Normalized Format

```json
{"amount":100.5,"description":"Test payment","customer_id":"12345"}
```

### Test Secret Key

```
test_secret_key_123456789
```

### Expected HMAC (SHA512 hex)

```
[Calculate using your implementation and verify it matches across all platforms]
```

### Validation Script

```javascript
// Node.js validation
const crypto = require('crypto');

function testHMAC() {
    const payload = '{"amount":100.5,"description":"Test payment","customer_id":"12345"}';
    const secretKey = 'test_secret_key_123456789';
    
    const hmac = crypto.createHmac('sha512', secretKey);
    hmac.update(payload);
    const result = hmac.digest('hex');
    
    console.log('HMAC Result:', result);
    return result;
}

const expectedHMAC = testHMAC();
// Compare this result across all your implementations
```

## Security Best Practices

### 1. Never Hardcode Secrets

```javascript
// ❌ NEVER do this
const HMAC_KEY = "edcb3xxxxf248b744653f052b22cexxxx";

// ✅ Always use environment variables
const HMAC_KEY = process.env.HMAC_KEY;
```

### 2. Use Secure Storage

* **Development:** `.env` files (add to `.gitignore`)
* **Production:** AWS Secrets Manager, Azure Key Vault, HashiCorp Vault
* **CI/CD:** Encrypted environment variables

### 3. Rotate Keys Regularly

* Implement key rotation every 90 days
* Support multiple active keys during rotation period
* Revoke old keys after transition

### 4. Log Safely

```javascript
// ❌ Never log the secret key
console.log('Secret Key:', secretKey);

// ❌ Never log the HMAC signature in production
console.log('HMAC:', hmacSignature);

// ✅ Log only success/failure
console.log('HMAC generated successfully');
```

### 5. Validate Input

```python
def generate_hmac(payload, secret_key):
    if not payload:
        raise ValueError("Payload cannot be empty")
    if not secret_key:
        raise ValueError("Secret key is required")
    if not isinstance(payload, (str, bytes)):
        raise TypeError("Payload must be string or bytes")
    
    # Generate HMAC...
```

## Next Steps

1. **Implement HMAC generation** in your preferred language using the examples above
2. **Test your implementation** with the provided test payload
3. **Integrate with API requests** - Include HMAC signature in all PIX Cash In/Out requests
4. **Review Auth Token endpoint** - Combine Bearer token + HMAC for complete authentication

## Related Documentation

* [Auth Token Endpoint](post_auth_token.md) - Generate OAuth 2.0 access tokens
* [Authentication API Overview](index.md) - Complete authentication guide