Skip to main content
This guide covers the HMAC signature authentication pattern used to secure requests to the Papermap Dashboard API.

How HMAC Authentication Works

The core security pattern uses HMAC-SHA256 to sign requests to the Papermap API:
  1. Concatenate workspace_id + valid_until timestamp
  2. Create HMAC-SHA256 hash using your secret key
  3. Send signature + timestamp in headers
  4. Papermap API verifies signature with the same secret

Authentication Flow

Your API → Generate HMAC Signature
   payload = "workspace-456" + "1699999999"
   signature = HMAC-SHA256(payload, secret_key)

Your API → Call Papermap Dashboard API
   POST ${PAPERMAP_API_URL}/api/v1/external/dashboards
   Headers:
     X-API-Key-ID: your-api-key
     X-Workspace-ID: workspace-456
     X-Valid-Until: 1699999999
     X-Signature: abc123...

Papermap API → Verifies Signature
   - Extracts workspace_id and valid_until
   - Computes: HMAC-SHA256(workspace_id + valid_until, secret_key)
   - Compares computed signature with X-Signature header
   - Checks valid_until hasn't expired
If the signature doesn’t match or the timestamp has expired, the request is rejected with a 401 Unauthorized error.

Implementation by Language

import hmac
import hashlib
import time

def _create_signature(workspace_id: str, valid_until: str, secret_key: str) -> str:
    """Create HMAC signature for authentication"""
    payload = f"{workspace_id}{valid_until}"
    signature = hmac.new(
        secret_key.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()
    return signature

def _get_auth_headers(workspace_id: str, api_key_id: str, secret_key: str) -> dict:
    """Generate authentication headers with HMAC signature"""
    valid_until = str(int(time.time()) + 300)  # Valid for 5 minutes
    signature = _create_signature(workspace_id, valid_until, secret_key)

    return {
        "X-API-Key-ID": api_key_id,
        "X-Workspace-ID": workspace_id,
        "X-Valid-Until": valid_until,
        "X-Signature": signature,
        "Content-Type": "application/json"
    }

Token Expiration

  • API requests: 5 minutes validity(advisable) based on the example above (valid_until = now + 300)
  • Expired tokens are automatically rejected

Security Best Practices

Never hardcode API credentials: - Always use environment variables or a secrets management system - The API endpoint URL should be treated as sensitive configuration - Store credentials securely and rotate them regularly

Environment Configuration

Store your credentials securely:
.env
PAPERMAP_API_KEY_ID=your-api-key-id
PAPERMAP_SECRET_KEY=your-secret-key-never-share
PAPERMAP_API_URL=<your-api-endpoint>
Obtaining Your Configuration: - API Credentials: Available in your Papermap dashboard under Settings → API Keys - API Endpoint: Available in Settings → API Configuration - Always use the values provided in your dashboard for your specific workspace

Next Steps