Request Signing
Our API uses JWT-based request signing to authenticate and verify the integrity of your requests. This guide explains how to implement request signing in your applications.Overview
Each request to our API must include a signed JWT token in the Authorization header. The token contains claims about the request and is signed using your private key with the RS256 algorithm.1
Prepare credentials
You need two credentials:
- API Key: Your unique identifier
- Private Key: Your RSA private key in PEM format
2
Extract URL path
Extract the path and query parameters from the request URL.
Do not include the domain or protocol in the signed data.
3
Generate body hash
Calculate a SHA-256 hash of the request body to ensure integrity.
4
Create and sign JWT
Create a JWT with specific claims and sign it with your private key.
5
Add Authorization header
Include the signed JWT in the Authorization header as a Bearer token.
Implementation
Below is a TypeScript implementation that you can use as a reference for other languages:JWT Payload Structure
The JWT payload must contain the following claims:The URL path with query parameters (excluding domain).
Example:
/v1/resources?filter=activeIssued at time as a Unix timestamp (seconds since epoch).
Expiration time as a Unix timestamp. Should be set to
iat + 55 seconds.Your API key.
SHA-256 hash of the request body as a hexadecimal string.
Language-Specific Implementations
- Node.js
- Python
- Java
- PHP
Testing Your Implementation
You can verify your implementation is working correctly by:- Generating a signed request
- Decoding the JWT at jwt.io to check the claims
- Making a test request to our API endpoint
Ensure your request body is identical between signature generation and the actual request.
Even a single whitespace difference will result in a different hash and signature validation failure.
Common Issues
Signature Verification Failed
Signature Verification Failed
This typically means:
- Your private key format is incorrect
- The body hash doesn’t match the actual request body
- The JWT has expired (should only be valid for 55 seconds)
Missing Required Claims
Missing Required Claims
Make sure your JWT includes all required claims:
uri, iat, exp, sub, and bodyHash.Incorrect URL Format
Incorrect URL Format
The
uri claim should only include the path and query string, not the domain or protocol.Security Best Practices
- Store your private key securely and never expose it in client-side code
- Generate a new JWT for each request
- Keep the expiration time short (55 seconds) to prevent replay attacks
- Implement proper error handling for failed authentication