Overview
The HopNow API uses HMAC (Hash-based Message Authentication Code) signatures to authenticate requests. This method ensures that:- Requests come from a verified source (authentication)
- Request data hasn’t been tampered with (integrity)
- Requests can’t be replayed (protection against replay attacks)
All API endpoints require HMAC authentication.
How HMAC Authentication Works
Each API request must include four authentication headers:
The API uses only HMAC headers for client API requests. Do not send an
Authorization: Bearer header for these endpoints.
Creating the Signature
Use the credential pair returned when you create an API key:api_key: send this value in theX-API-Keyheadersecret: use this value as the HMAC-SHA256 signing key
- Constructing the payload from request components
- Creating an HMAC-SHA256 hash using your API secret
- Converting to hexadecimal representation
Signature Payload Format
The payload for signing consists of these components concatenated together:- HTTP_METHOD: Uppercase HTTP method (
GET,POST,PATCH,DELETE) - PATH_AND_QUERY: The URL path exactly as sent to HopNow, starting with
/, followed by?and the query string when the request has query parameters. Do not include the scheme, host, port, or fragment. - TIMESTAMP: Unix timestamp as a string
- NONCE: Unique random token (32 hex characters)
- BODY: Exact request body string sent over the wire (empty string for GET requests)
- Request URL
https://api.hopnow.io/v1/customers/cus_abc123/accountssigns/v1/customers/cus_abc123/accounts - Request URL
https://api.hopnow.io/v1/customers/cus_abc123/accounts?page=1&size=10signs/v1/customers/cus_abc123/accounts?page=1&size=10
Step-by-Step Example
Let’s create a signature for this request:Implementation Examples
Python
JavaScript/Node.js
cURL
Authentication Headers Reference
X-API-Key
Theapi_key value returned when you create an API key. This identifies the key used for the request.
X-Signature
The HMAC-SHA256 signature of your request, encoded as a lowercase hexadecimal string.X-Timestamp
Unix timestamp indicating when the request was created. Requests older than 5 minutes are rejected.X-Nonce
Unique random token to prevent replay attacks. Must be 32 hexadecimal characters (16 bytes).Security Best Practices
1. Secure Storage
- Store API secrets in environment variables or secure key management systems
- Never hardcode secrets in your application code
- Use different API keys for different environments (development, staging, production)
2. Request Validation
- Always generate a new nonce for each request to prevent replay attacks
- Ensure nonces are cryptographically random (use
secrets.token_hex()in Python orcrypto.randomBytes()in Node.js) - Validate timestamps to prevent replay attacks beyond the nonce window
- Implement request timeouts to avoid hanging requests
- Log authentication failures for security monitoring
3. Error Handling
- Don’t expose authentication details in error messages
- Implement proper retry logic with exponential backoff
- Monitor for unusual authentication patterns
Common Issues and Troubleshooting
Invalid Signature Error
- Incorrect payload construction (ensure format:
{METHOD}{PATH_AND_QUERY}{TIMESTAMP}{NONCE}{BODY}) - Signing the full URL instead of only the path and query string
- Wrong HTTP method case (must be uppercase)
- Missing or incorrect timestamp/nonce
- Query string ordering or encoding differences between the signed payload and the actual request
- Incorrect secret key
Timestamp Too Old Error
Nonce Replay Error
Missing Headers Error
X-API-Key, X-Signature, X-Timestamp, X-Nonce) are included in every request.
Testing Your Implementation
Use a real GET endpoint to verify your authentication implementation. For example, list one account for a customer you own:Need help with authentication? Review the examples above or contact support.