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:
Concatenate workspace_id + valid_until timestamp
Create HMAC-SHA256 hash using your secret key
Send signature + timestamp in headers
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
Python
TypeScript/Node.js
PHP
Java
C#
Go
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:
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