Authentication and HMAC
Every Evaluate request uses an API key and the version 2 HMAC-SHA256 signing contract.
Headers
Section titled “Headers”| Header | Required | Description |
|---|---|---|
Content-Type |
Yes | Must be application/json. |
X-API-Key |
Yes | Identifies and authenticates the calling tenant. |
X-Signature-Version |
Yes | Must be v2. |
X-Timestamp |
Yes | Current ISO 8601 request time; it must be within five minutes of server time. |
X-Request-ID |
Yes | A fresh UUID generated for each request attempt. |
X-Signature |
Yes | Hex-encoded HMAC-SHA256 digest of the exact raw request body, using the tenant’s HMAC secret. |
The API key and HMAC secret are different credentials. Do not use the API key as the HMAC secret.
Signature algorithm
Section titled “Signature algorithm”signature = lowercase_hex( HMAC-SHA256( key = UTF8(hmac_secret), message = exact_raw_request_body_bytes ))The signature covers the request body only. X-Signature-Version, X-Timestamp, and X-Request-ID are not included in the signed bytes.
Correct sequence
Section titled “Correct sequence”- Construct the request object.
- Serialize it once to UTF-8 JSON.
- Calculate HMAC-SHA256 over those exact bytes.
- Send those same bytes as the HTTP body.
- Generate a fresh UUID for
X-Request-IDand the current timestamp forX-Timestamp. - Set
X-Signature-Versiontov2and put the hexadecimal digest inX-Signature.
Whitespace, property order, and numeric formatting affect the signature. They may be changed before signing, but not between signing and transmission.
Language examples
Section titled “Language examples”The 5-minute Quickstart contains complete, runnable examples for cURL, Node.js, Python, Java, and Go. Each example builds the payload, serializes it once, computes the signature, sends the exact signed bytes, checks the HTTP status, and prints the response.
Use those complete examples as the language reference; avoid copying isolated HMAC fragments that do not also control HTTP serialization.
Timestamp and request-ID behavior
Section titled “Timestamp and request-ID behavior”- Omitted
X-Timestamp: rejected because the header is required. - Malformed
X-Timestamp:400 Bad Request. - More than five minutes from server time:
401 Unauthorized. - Omitted or malformed
X-Request-ID: rejected because every request requires a fresh UUID.
Sending a timestamp and request ID does not make a request idempotent. See Reliability and reconciliation.