Configuration
Configure webhook endpoints in the Embed Portal under Webhooks. Up to 5 endpoints per environment, each with its own signing secret.
Test webhooks
Use the Webhook Playground in the Embed Portal to send test webhooks with selectable event types and custom payloads. This verifies both connectivity and your signature verification logic.
Event types
| Event | Description |
|---|
score.completed | Scoring finished with results |
score.failed | Scoring failed with error details |
batch.completed | All jobs in a batch finished (completed or failed) |
Webhooks are sent when a scoring job finishes. Returning an already completed scoring job through idempotency does not send a new score.completed webhook. See Idempotency for duplicate submission behavior.
Payload: score.completed
Payload: score.failed
Payload: batch.completed
Status values: completed (all succeeded) or failed (at least 1 failed).
Signature verification
Webhooks are signed with HMAC-SHA256. Always verify signatures.
Headers:
| Header | Value |
|---|
X-Webhook-Id | Unique delivery ID (stable across retries) |
X-Webhook-Signature | t=<unix_seconds>,v1=<hex_digest> |
X-Webhook-Event | Event type |
X-Webhook-Timestamp | Unix timestamp (seconds) |
Using the SDK (recommended)
The SDK rejects webhooks older than 5 minutes by default. Override with options: { toleranceInSeconds: 600 }.
Manual verification
Signature header format: t=<unix_seconds>,v1=<hex_digest>. The digest covers {timestamp}.{raw_body}.
Always use timing-safe comparison functions to prevent timing attacks.
IP whitelisting
Signature verification is sufficient for most integrations. If your security policy requires IP whitelisting on top, contact us through the Embed Portal for current webhook source IP ranges.
Retry policy
- Up to 5 attempts with exponential backoff and jitter
- Delay range: 1 minute to 30 minutes
After all retries fail, results stay accessible via GET /v1/jobs/{jobId}/applications/{applicationId}/scoring-jobs/{scoringJobId}.
Always implement a polling fallback. Check for applications stuck in “scoring” status and poll after a timeout (5 minutes is a good default).
Manual retry of failed scoring jobs
Portal admins can retry permanently failed scoring runs from the Monitoring page. A successful retry resets the same scoringJobId back to pending, so your webhook consumer may receive score.failed followed by score.completed (or another score.failed) for the same ID.
Don’t treat score.failed as a permanent terminal state per scoringJobId. If you cache results keyed on scoringJobId, update the cache when a later score.completed arrives for the same ID.
Deduplication
Use the X-Webhook-Id header as a deduplication key. This ID is stable across retries. Webhooks may be delivered more than once.