Skip to content

Call Recording Encryption Configuration Guide

Overview

This guide explains how to configure HIPAA-compliant encryption for call recordings in your account using our API. Encrypting recordings ensures that sensitive call data is protected both in transit and at rest, meeting security and compliance requirements.


What is Recording Encryption?

Recording encryption protects your call recordings by converting the audio data into an encrypted format that can only be accessed with the proper encryption keys. This ensures that even if recordings are accessed by unauthorized parties, the data remains protected.

Key Benefits: - HIPAA Compliance: Meets healthcare data protection requirements - Data Security: Protects sensitive customer information - Access Control: Only authorized parties can decrypt and access recordings - Regulatory Compliance: Helps meet various industry regulations


API Endpoints

Get Current Encryption Configuration

Retrieve the current encryption settings for your account.

Endpoint:

GET /api/v2/config/call_recording_encryption

Headers: - X-Account-ID: Your account identifier - Authorization: Bearer JWT token

Example Request:

curl -X GET "https://api.example.com/api/v2/config/call_recording_encryption" \
  -H "X-Account-ID: your_account_id" \
  -H "Authorization: Bearer your_jwt_token"

Example Response:

{
  "success": true,
  "config": {}
}


Configure Encryption Settings

Enable or update encryption settings for your account.

Endpoint:

PUT /api/v2/config/call_recording_encryption

Headers: - X-Account-ID: Your account identifier - Authorization: Bearer JWT token - Content-Type: application/json

Example Request:

curl -X PUT "https://api.example.com/api/v2/config/call_recording_encryption" \
  -H "X-Account-ID: your_account_id" \
  -H "Authorization: Bearer your_jwt_token" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "algorithm": "AES-256-GCM",
    "salt": "unique_salt_value",
    "key": "your_encryption_key_here_at_least_32_characters"
  }'

Note: key_version and key_id are automatically managed by the backend and should not be provided in the request. They will be returned in the response for reference only.

Example Response:

{
  "success": true,
  "message": "Encryption configuration updated successfully",
  "config": {
    "enabled": true,
    "algorithm": "AES-256-GCM",
    "key_version": 1,
    "key_id": "key_auto_your_acc",
    "salt": "unique_salt_value",
    "key": "your_encryption_key_here_at_least_32_characters",
    "historical_keys": {},
    "historical_salts": {}
  }
}


Configuration Parameters

enabled (Required)

What it does: Activates or deactivates encryption for your account.

Type: Boolean (true or false)

Values: - true: Enables encryption. All new recordings will be encrypted before storage. - false: Disables encryption. New recordings will be stored unencrypted.

Important Notes: - This is the only required field to enable basic encryption - When set to true, default values will be applied for other parameters if not specified - Changing this setting only affects new recordings; existing recordings retain their current encryption status

Example:

{
  "enabled": true
}


algorithm (Optional)

What it does: Specifies which encryption method to use for protecting your recordings.

Type: String

Supported Values: - "AES-256-GCM" (Recommended): Modern, secure encryption with built-in authentication - "AES-256-CBC": Standard encryption method, widely supported

Default: "AES-256-GCM" (when enabled is true)

What this means for you: - AES-256-GCM: More secure, includes authentication to prevent tampering. Recommended for new implementations. - AES-256-CBC: Traditional encryption method, compatible with older systems.

Best Practice: Use AES-256-GCM unless you have specific compatibility requirements.

Example:

{
  "enabled": true,
  "algorithm": "AES-256-GCM"
}


key_version (Read-only in Response)

What it does: Identifies which version of your encryption key is currently being used. This is automatically managed by the backend and cannot be set in requests.

Type: Integer (positive number, read-only)

How it works: - Automatically starts at 1 when encryption is first enabled - Automatically increments when you change key or salt values - Each version corresponds to a specific encryption key/salt pair - Older recordings encrypted with version 1 can still be accessed with version 1 keys - New recordings will use the current version number - This allows automatic key rotation without losing access to historical recordings

Important: You cannot set key_version in requests. It is managed internally and shown in responses for reference only.

Example Response (showing key_version):

{
  "config": {
    "enabled": true,
    "key_version": 1,
    "key": "...",
    "salt": "..."
  }
}


key_id (Read-only in Response)

What it does: Provides a unique identifier for your encryption key. This is automatically generated by the backend and cannot be set in requests.

Type: String (read-only)

Auto-Generation: The system automatically generates a unique key ID based on your account identifier (format: key_auto_<account_prefix>).

Important: You cannot set key_id in requests. It is managed internally and shown in responses for reference only.

Example Response (showing key_id):

{
  "config": {
    "enabled": true,
    "key_id": "key_auto_b02d27af63",
    "key": "..."
  }
}


salt (Optional)

What it does: Adds an extra layer of security by mixing a random value with your encryption process. This prevents attackers from using pre-computed tables to crack your encryption.

Type: String (base64-encoded or plain text)

Required: No

Auto-Generation: If not provided, the system will automatically generate a cryptographically secure 128-bit salt (16 bytes, base64-encoded to 24 characters). This generated salt will be returned in the API response.

Restrictions: - Cannot be "default_salt" (this value is rejected for security reasons)

What this means: - Salt is like adding a unique "spice" to each account's encryption - Makes encryption stronger by preventing pattern-based attacks - Should be unique per account for maximum security - The salt is stored in each recording's metadata - this allows decryption even if the salt configuration changes - Historical salts are preserved - when you rotate salts, old salts are stored in historical_salts map - If you don't provide one, a secure salt will be auto-generated and returned in the response

Salt Storage and Rotation: - Each recording stores its salt in metadata (allows backward compatibility) - When you provide a new salt (different from current), the system automatically: - Increments key_version - Moves the current salt to historical_salts[old_version] - Moves the current key to historical_keys[old_version] (for backward compatibility) - Stores the new salt for the new version - Gorec can decrypt old recordings using the salt stored in their metadata or from historical_salts - System automatically manages historical_salts map - no manual intervention needed

Security Recommendation: - Save the generated salt: If the system generates a salt for you, save it securely from the API response - Use a unique, random value for each account if providing manually - Generate using cryptographically secure random number generators - Historical salts are preserved automatically during rotation - Never reuse salt values across accounts

Validation: The API will reject encryption configuration if: - The salt matches the insecure default value "default_salt"

Example - With your own salt:

{
  "enabled": true,
  "salt": "unique_random_value_for_account_001"
}

Example - Auto-generated:

{
  "enabled": true
}
The system will generate a secure salt automatically.


What it does: The actual encryption key used to encrypt and decrypt recordings. This is a plain text key that will be automatically converted to base64 for secure storage in the database.

Type: String (plain text key)

Required: No, but strongly recommended

Format: Plain text string, minimum 32 characters long

Auto-Generation: If not provided, the system will automatically generate a cryptographically secure 256-bit key as a readable hexadecimal string (64 hex characters). This generated key will be returned in the API response for you to save securely.

Security Requirements (if provided): - Minimum Length: Must be at least 32 characters long (plain text) - Cannot be default values: Values like "default_encrypted_key", "default", "test", or other insecure defaults are rejected - Should be unique: Each account should have a unique key

What this means: - You provide the key in plain text (no need to encode in base64 manually) - The system automatically converts your plain text key to base64 before storing it in the database - Used directly by the encryption service (Gorec) to encrypt/decrypt recordings - Required to decrypt recordings later - The key is stored as base64 in the database for compatibility, but you work with it in plain text - If you don't provide one, a secure readable key (hexadecimal) will be auto-generated and returned in the response

Important Security Notes: - Save the generated key: If the system generates a key for you, save it securely from the API response - The key you provide should be in plain text - the system handles base64 conversion automatically - Transmit keys securely over HTTPS only - Store keys in secure key management systems on your side - Keys must meet minimum security requirements (minimum 32 characters) if provided manually - Auto-generated keys are hexadecimal strings (readable, like: 1a2b3c4d5e6f...)

Validation: The API will reject encryption configuration if: - The key is provided but shorter than 32 characters - The key matches insecure default values

Example - With your own key (plain text):

{
  "enabled": true,
  "key": "my_secure_encryption_key_at_least_32_characters_long"
}

Example - Letting system generate (recommended for simplicity):

{
  "enabled": true
}
The response will include the generated key that you should save securely.


How Encryption Works

Basic Flow

  1. Configuration: You configure encryption settings via the API
  2. Key Management: Your encryption keys are securely stored and managed
  3. Recording Creation: When a call is recorded, the system:
  4. Generates a unique identifier for the recording
  5. Uses your encryption key to encrypt the audio data
  6. Stores metadata (key ID, version, algorithm) with the recording
  7. Saves the encrypted recording to storage
  8. Recording Access: When you access a recording:
  9. The system retrieves your encryption configuration
  10. Uses the stored metadata to identify the correct key and version
  11. Decrypts the recording for authorized access

Automatic Key Version Management

The key_version is automatically managed by the backend. You don't need to (and cannot) set it manually. The system automatically handles key rotation when you change key or salt values.

Scenario 1: Initial Setup - Enable encryption with your first encryption key (plain text) - System automatically sets key_version: 1 - All recordings are encrypted with version 1 - historical_keys and historical_salts maps are empty

Scenario 2: Automatic Key Rotation - Provide a new encryption key (different from current) OR a new salt (different from current) - The system automatically: - Detects the change - Increments key_version (e.g., 1 → 2) - Moves the current key to historical_keys[old_version] - Moves the current salt to historical_salts[old_version] - Stores the new key as key for the new version - Stores the new salt as salt for the new version - Preserves all historical keys and salts in their respective maps - New recordings use the new version's key and salt (stored in recording metadata) - Old recordings remain accessible using old version's key and salt from historical_keys and historical_salts, or from their stored metadata - Both versions remain active for decryption - Each recording stores its salt in metadata - allowing decryption even if configuration changes

Important: Even if you only change key or only change salt, the system will preserve BOTH the old key and old salt in historical maps. This ensures you can decrypt recordings encrypted with any previous version.

Benefits of Automatic Key Versioning: - ✅ Automatic version management - no manual version tracking needed - ✅ Automatic historical key preservation - no manual management needed - ✅ Maintain access to historical recordings across all key versions - ✅ Security through regular key rotation - ✅ Compliance with key rotation policies - ✅ Smooth transitions between key generations - ✅ The historical_keys and historical_salts maps store all previous versions automatically


Getting Started

Step 1: Check Current Configuration

First, check if encryption is already enabled:

curl -X GET "https://api.example.com/api/v2/config/call_recording_encryption" \
  -H "X-Account-ID: your_account_id" \
  -H "Authorization: Bearer your_jwt_token"

Step 2: Enable Encryption (Simple Method)

Enable encryption with auto-generated secure values:

curl -X PUT "https://api.example.com/api/v2/config/call_recording_encryption" \
  -H "X-Account-ID: your_account_id" \
  -H "Authorization: Bearer your_jwt_token" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true
  }'

⚠️ IMPORTANT: The response will include auto-generated key, salt, key_version, and key_id values. Save the key and salt securely - you'll need them to decrypt your recordings! The key_version and key_id are shown for reference only.

Response Example:

{
  "success": true,
  "message": "Encryption configuration updated successfully",
  "config": {
    "enabled": true,
    "algorithm": "AES-256-GCM",
    "key_version": 1,
    "key_id": "key_auto_b02d27af63",
    "salt": "KxY9mP2qR8vN3wT6...",  // ⚠️ SAVE THIS
    "key": "1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef1234567890"  // ⚠️ SAVE THIS (readable hex format)
  }
}

Step 2 (Alternative): Enable Encryption with Your Own Keys

If you prefer to provide your own keys for advanced key management:

curl -X PUT "https://api.example.com/api/v2/config/call_recording_encryption" \
  -H "X-Account-ID: your_account_id" \
  -H "Authorization: Bearer your_jwt_token" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "algorithm": "AES-256-GCM",
    "salt": "your_unique_salt_value",
    "key": "your_encryption_key_must_be_at_least_32_characters_long"
  }'

Note: - key_version and key_id are automatically managed - do not include them in requests - key must be at least 32 characters (plain text, no base64 needed) - salt cannot be "default_salt" - The system will auto-generate key_id and start key_version at 1

Step 3: Configure Advanced Settings (Optional)

For production use, configure with specific values:

curl -X PUT "https://api.example.com/api/v2/config/call_recording_encryption" \
  -H "X-Account-ID: your_account_id" \
  -H "Authorization: Bearer your_jwt_token" \
  -H "Content-Type: application/json" \
  -d '{
    "enabled": true,
    "algorithm": "AES-256-GCM",
    "key_version": 1,
    "key_id": "key_production_001",
    "salt": "your_unique_salt_value",
    "key": "your_encryption_key_value_at_least_32_characters"
  }'

Step 4: Verify Configuration

Confirm your settings were applied:

curl -X GET "https://api.example.com/api/v2/config/call_recording_encryption" \
  -H "X-Account-ID: your_account_id" \
  -H "Authorization: Bearer your_jwt_token"

Common Use Cases

⚠️ Important: Saving Auto-Generated Values

When enabled: true without providing all fields:

First-time enabling (encryption was disabled): - key: Auto-generated 256-bit secure key (readable hexadecimal format) - key_id: Auto-generated unique identifier based on your account - salt: Auto-generated 128-bit secure salt (base64-encoded)

Re-enabling (encryption was previously disabled): - Existing values are preserved - the system will keep your current key, salt, and key_id if: - There are valid values stored in the database (even if encryption was disabled) - You don't provide new key or salt values in the request - The system maintains the same key_version unless you change key or salt

Note: This works even if encryption was previously disabled (enabled: false) but had valid encryption configuration stored. When you re-enable without providing new key or salt, the system will preserve your stored keys and maintain the same version.

⚠️ CRITICAL: When new values are auto-generated (first time or key rotation), they are returned in the API response. You must save them securely as you'll need them to access your encrypted recordings in the future.

Simple Encryption Configuration

The easiest way to enable encryption is to just set enabled: true and let the system generate secure values:

{
  "enabled": true
}

Response (first time enabling):

{
  "success": true,
  "message": "Encryption configuration updated successfully",
  "config": {
    "enabled": true,
    "algorithm": "AES-256-GCM",
    "key_version": 1,
    "key_id": "key_auto_b02d27af63",
    "salt": "aBc123XyZ456...",  // Save this!
    "key": "1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef1234567890",  // Save this!
  }
}

Response (re-enabling with same key_version): If encryption was previously configured (even if disabled) and you send the same request, the system will preserve your existing values:

{
  "success": true,
  "message": "Encryption configuration updated successfully",
  "config": {
    "enabled": true,
    "algorithm": "AES-256-GCM",
    "key_version": 1,
    "key_id": "key_auto_b02d27af63",  // Preserved
    "salt": "aBc123XyZ456...",  // Preserved - same as before
    "key": "1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef1234567890",  // Preserved - same as before
  }
}

⚠️ IMPORTANT: - When new values are generated (first time or key rotation), save the key and salt values from the response in a secure location - When existing values are preserved, you can verify they match your stored values

Example - Re-enabling after disabling: If you previously disabled encryption (enabled: false) but had valid encryption keys stored:

// Database state before request:
{
  "enabled": false,
  "key_version": 1,
  "key": "stored_key_from_before...",
  "salt": "stored_salt_from_before...",
  "key_id": "key_production_001"
}

// Request:
{
  "enabled": true
}

// Result: System preserves stored values and re-enables encryption
{
  "enabled": true,
  "key_version": 1,
  "key": "stored_key_from_before...",  // Preserved!
  "salt": "stored_salt_from_before...",  // Preserved!
  "key_id": "key_production_001"  // Preserved!
}

This ensures you can re-enable encryption without losing access to previously encrypted recordings.


Production Configuration

For production environments, configure all parameters:

{
  "enabled": true,
  "algorithm": "AES-256-GCM",
  "key_version": 1,
  "key_id": "key_production_account_001",
  "salt": "unique_production_salt_2024",
  "key": "production_encryption_key_value_at_least_32_characters"
}

Best Practices: - Use descriptive key IDs that identify the environment - Use unique salt values per account - Store encrypted keys securely - Document your key rotation schedule


Disabling Encryption

To disable encryption (recordings will be stored unencrypted):

{
  "enabled": false
}

Important Behavior: - Existing encryption values are preserved - The system keeps your key, salt, key_id, and key_version even when encryption is disabled - This ensures you can re-enable encryption with the same keys later - Existing encrypted recordings remain encrypted and accessible when you re-enable - New recordings will be stored without encryption while disabled - Consider data retention and compliance requirements before disabling

Example - Disabling preserves values:

// Request to disable
{
  "enabled": false
}

// Response - values are preserved
{
  "enabled": false,
  "algorithm": "AES-256-GCM",
  "key_version": 2,
  "key_id": "key_production_001",  // Preserved
  "salt": "stored_salt_value...",  // Preserved
  "key": "stored_key_value..."  // Preserved
}

When you re-enable with {"enabled": true}, these preserved values will be used automatically.


Key Rotation

To rotate encryption keys and maintain access to historical recordings:

How Key Rotation Works:

  1. Current Key Management: The system automatically manages historical keys for you
  2. Automatic Preservation: When you rotate to a new key_version, the current key is automatically moved to historical_keys
  3. Historical Access: All previous key versions are stored in historical_keys map, allowing access to old recordings

Example - Rotating from version 1 to version 2:

Before rotation:

{
  "enabled": true,
  "key_version": 1,
  "salt": "KxY9mP2qR8vN3wT6sA7bC4dF1gH8j=",
  "key": "1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef1234567890",
  "historical_keys": {},
  "historical_salts": {}
}

Request to rotate (simply provide new key or salt):

{
  "enabled": true,
  "algorithm": "AES-256-GCM",
  "salt": "bmV3X3NhbHRfZm9yX3ZlcnNpb25fMg==",
  "key": "new_encryption_key_plain_text_at_least_32_characters_long"
}
Note: You don't need to (and cannot) specify key_version or key_id. The system automatically increments key_version when it detects changes to key or salt.

After rotation (automatic):

{
  "enabled": true,
  "key_version": 2,
  "salt": "bmV3X3NhbHRfZm9yX3ZlcnNpb25fMg==",
  "key": "new_encryption_key_plain_text_at_least_32_characters_long",
  "historical_keys": {
    "1": "1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef1234567890"
  },
  "historical_salts": {
    "1": "KxY9mP2qR8vN3wT6sA7bC4dF1gH8j="
  }
}

What happens automatically: - System detects changes to key and/or salt - System automatically increments key_version from 1 to 2 - Old key (version 1) is automatically moved to historical_keys[1] - Old salt (version 1) is automatically moved to historical_salts[1] - New key and salt are stored for version 2 - Both keys and salts remain accessible for decrypting recordings - New recordings use version 2 key and salt - Old recordings remain accessible with version 1 key and salt (from historical_keys and historical_salts)

Important: The system preserves BOTH the old key and old salt, even if you only changed one of them. This ensures backward compatibility.

Key Points: - ✅ Automatic version increment when key or salt changes - ✅ Historical keys and salts are automatically preserved - ✅ No manual intervention needed for version management or key/salt storage - ✅ All key and salt versions remain accessible - ✅ System manages both historical_keys and historical_salts maps automatically - ✅ Both old key AND old salt are always preserved together, ensuring complete backward compatibility - ✅ Each recording stores its salt in metadata for backward compatibility - ✅ Gorec can decrypt recordings using stored metadata or historical values


Security Best Practices

1. Use Strong Configuration

Always configure all parameters in production:

  • Use AES-256-GCM algorithm
  • Set unique key IDs for easy identification
  • Use unique salt values per account
  • Never reuse keys across accounts

2. Regular Key Rotation

Implement a key rotation schedule:

  • Rotate keys at least annually (more frequently for high-security environments)
  • Increment key_version with each rotation
  • Maintain access to previous key versions
  • Document key rotation dates

3. Secure Key Management

  • Never transmit unencrypted keys
  • Store keys in secure key management systems
  • Limit access to encryption keys
  • Monitor key usage and access

4. Monitor Configuration

  • Regularly verify encryption is enabled
  • Check that configurations haven't been unexpectedly changed
  • Review access logs to encryption endpoints

Troubleshooting

Issue: "Could not get account ID from context"

Solution: Ensure you're including the X-Account-ID header in your request.

Issue: "Failed to update encryption configuration"

Solution: - Verify your account ID is correct - Ensure you have admin permissions - Check that all required fields are included

Issue: Cannot decrypt old recordings

Solution: - Verify the key_version matches the version used for old recordings - Ensure old encryption keys are still available - Check that the key ID and encrypted key are correct

Issue: Configuration not applied

Solution: - Verify the request was successful (check response status) - Retrieve configuration to confirm changes were saved - Wait a few moments for changes to propagate


API Response Codes

Code Meaning Action
200 Success Configuration retrieved/updated successfully
400 Bad Request Invalid request body or missing required fields
401 Unauthorized Invalid or missing JWT token
403 Forbidden User lacks required permissions
404 Not Found Account or endpoint not found
500 Internal Server Error Server-side error occurred

Compliance Considerations

HIPAA Requirements

Encryption helps meet HIPAA requirements for protecting Protected Health Information (PHI) in call recordings:

  • Encryption at Rest: Ensures recordings are encrypted when stored
  • Access Controls: Only authorized parties can decrypt recordings
  • Audit Trails: Key versioning provides audit capability

Other Regulations

Recording encryption also helps meet: - GDPR data protection requirements - PCI-DSS for payment card information - SOC 2 security controls - Industry-specific compliance needs


Support and Resources

Getting Help

If you need assistance with encryption configuration:

  1. Check this documentation for common issues
  2. Review API responses for specific error messages
  3. Contact support with your account ID and error details

Additional Resources

  • API Authentication Guide
  • Account Management Documentation
  • Security Best Practices Guide

Summary

Recording encryption provides essential security for your call recordings:

  • Enable encryption by setting enabled: true
  • Configure parameters for production use
  • Use key versioning for secure key rotation
  • Follow best practices for maximum security

Start with basic encryption using defaults, then configure advanced settings as needed. Remember to verify your configuration and maintain proper key management practices.


Last Updated: 2025-10-29