Grain signs all webhook payloads with an HMAC signature so you can verify they originated from Grain and haven’t been tampered with.Documentation Index
Fetch the complete documentation index at: https://docs.grainfinance.co/llms.txt
Use this file to discover all available pages before exploring further.
Headers
Each webhook request includes two security headers:| Header | Description |
|---|---|
| X-Grain-Signature | HMAC-SHA256 signature in format v1={signature} |
| X-Grain-Timestamp | Unix timestamp (seconds) when the request was signed |
Verification Steps
- Extract the timestamp and signature from the request headers.
- Check the timestamp is within an acceptable window (recommended: 5 minutes). This protects against replay attacks.
- Compute the expected signature using your webhook secret.
- Compare signatures using a timing-safe comparison function.
Computing the Signature
The signature is computed over the string{timestamp}.{raw_request_body}:
Python Example
Important Notes
- Always use the raw request body — do not parse and re-serialize the JSON, as this may change the payload.
- Use timing-safe comparison — standard string comparison is vulnerable to timing attacks.
- Validate the timestamp — this protects against replay attacks where an attacker resends a captured request.
- Store your secret securely — treat it like a password; never commit it to source control.