Receive Webhook Updates
Receive real-time status updates for workflow runs. Your webhook endpoint will receive POST requests as the workflow progresses through processing, success, or failure states.
Setup Your Webhook
Before receiving webhooks, you need to generate a secure secret and share it with Nen.Generate a webhook secret
Share your secret with Nen
Set up your webhook endpoint
Webhook Statuses
Your webhook endpoint will receive three types of status updates:- Processing
- Success
- Failed
Webhook HMAC Validation
Nen secures all webhook requests using HMAC-SHA256 signatures. This cryptographic validation ensures that incoming webhook events originate from Nen and have not been tampered with during transmission.HMAC Validation Process
Each webhook request includes an HMAC signature in theX-Hmac-Signature header. Your application must:
- Extract the signature from the request header
- Compute the expected signature using your shared secret and the raw request body
- Compare signatures using a timing-safe comparison to prevent timing attacks
Required Header
sha256= followed by the lowercase hexadecimal HMAC-SHA256 digest.
Signature Calculation
The HMAC signature is calculated using:- Algorithm: HMAC-SHA256 (RFC 2104 compliant)
- Secret Key: Your webhook secret (generated during setup)
- Message: Raw request body (UTF-8 encoded JSON)
- Output: Lowercase hexadecimal string
Implementation Examples
First, create a reusable verification function:HMAC Security Requirements
Use cryptographically secure implementations
Use cryptographically secure implementations
crypto.createHmac() in Node.js, hmac.new() in Python). These implementations are:- RFC 2104 compliant: Follow the official HMAC specification
- Constant-time safe: Protect against timing attack vulnerabilities
- Battle-tested: Widely audited and maintained by security experts
Protect your webhook secret
Protect your webhook secret
- Store securely: Use environment variables or a secrets manager (AWS Secrets Manager, HashiCorp Vault, etc.)
- Never commit: Add secrets to
.gitignoreand.env.examplefiles - Rotate regularly: Generate new secrets periodically and update with your Nen contact
- Limit access: Only share with team members who need it
- Use separate secrets: Different secrets for staging and production environments
Always use timing-safe comparisons
Always use timing-safe comparisons
=== or ==) can leak timing information that attackers exploit. Always use timing-safe comparison functions:- Node.js:
crypto.timingSafeEqual() - Python:
hmac.compare_digest() - Go:
crypto/subtle.ConstantTimeCompare()
Validate before processing
Validate before processing
- Extract signature from header
- Validate HMAC signature (reject if invalid)
- Parse JSON payload (only after signature is verified)
- Process webhook data
Handling Webhook Payloads
Once verified, process the webhook based on the status:200 OK response quickly (within 5 seconds) to acknowledge receipt. Process the webhook data asynchronously if needed.Best Practices
Store message IDs
Store message IDs
message_id values in your database to prevent processing duplicate webhooks:Handle URL expiration
Handle URL expiration
Monitor webhook health
Monitor webhook health
Troubleshooting
Webhooks not arriving
Webhooks not arriving
- Your webhook URL is not publicly accessible
- Firewall is blocking incoming requests
- SSL certificate issues on your domain
- Test your webhook URL with tools like webhook.site
- Ensure your server accepts POST requests
- Verify SSL certificates are valid and not self-signed
- Check firewall rules to allow traffic from Nen
HMAC signature validation failing
HMAC signature validation failing
- Using incorrect webhook secret
- Validating parsed JSON instead of raw request body
- Character encoding mismatches (non-UTF-8)
- Request body modified before validation
- Missing or malformed
X-Hmac-Signatureheader
- Verify you’re using the webhook secret you generated during setup (not your API key)
- Validate the raw request body before parsing JSON (
request.datain Flask,req.bodywithexpress.raw()in Express,request.rawBodyin Fastify) - Ensure UTF-8 encoding for all string operations
- Check header extraction:
request.headers['X-Hmac-Signature']orreq.headers['x-hmac-signature'] - Log both expected and received signatures for debugging (securely, without exposing the secret)
Presigned URLs not working
Presigned URLs not working
- URLs have expired
- URLs accessed after expiration timestamp
- Network issues preventing download
- Check the
expires_attimestamp before downloading - Download files immediately upon receiving success webhook
- Implement retry logic with exponential backoff
- Store files in your own storage system
Authorizations
Your Nen API key. Requests that include secure_workflow_params must additionally be HMAC-signed — see Secure Parameters.
Body
Workflow status update
- Option 1
- Option 2
- Option 3
The workflow ID being executed
"12345678-1234-1234-1234-123456789abc"
Unique identifier for this workflow run
"550e8400-e29b-41d4-a716-446655440000"
Current status of the workflow
processing "processing"
Unix timestamp when presigned URLs expire
1730319600
Response
Return a 200 status to acknowledge receipt of the webhook