Webhooks
Get notified when jobs complete instead of polling. Webhooks are signed, retried automatically, and tracked with health states so you know when delivery fails.
Setting up webhooks
Go to Dashboard → Webhooks to add an endpoint. By default, endpoints subscribe to job.completed and job.failed events.
job.completedFired when a scan or classify job finishes successfully.
job.failedFired when a job fails after all retry attempts are exhausted.
billing.topup_succeededAuto-topup payment was processed successfully.
billing.topup_failedAuto-topup payment failed.
Testing your endpoint
Use POST /v1/webhooks/test to send a test delivery before going live:
curl -X POST https://api.on-page.ai/v1/webhooks/test \
-H "Authorization: Bearer op_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.example/webhooks/onpage",
"event": "job.completed"
}'The response includes a signing_secret so you can verify the test delivery signature matches.
Verifying signatures
Every delivery includes these headers:
OnPage-Signature: <hmac-sha256(timestamp.body)>
OnPage-Timestamp: <unix-seconds>
OnPage-Delivery-Id: <delivery-id>
OnPage-Event: <event-name>
User-Agent: OnPage-Webhooks/1.0The signature is computed as HMAC-SHA256(signing_secret, timestamp + "." + raw_body). Verify by recomputing the HMAC with your stored signing secret and comparing the result.
Node.js verification example
import crypto from "crypto";
function verifyWebhook(body, headers, secret) {
const timestamp = headers["onpage-timestamp"];
const signature = headers["onpage-signature"];
const expected = crypto
.createHmac("sha256", secret)
.update(timestamp + "." + body)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}Retries and endpoint health
Automatic retries
Failed deliveries retry with exponential backoff — up to 8 attempts over roughly 48 hours. Your endpoint should return a 2xx response quickly to avoid retries.
Endpoint health states
Endpoints move through active, degraded, and paused states as failures accumulate. After 20 consecutive failures, the endpoint is paused. Check the dashboard to re-enable it.
Best practices
Respond quickly
Return a 200 immediately, then process the payload async. Slow responses count as failures and trigger retries.
Always verify signatures
Don't process unverified payloads. An attacker could send fake completions to your endpoint.
Handle duplicates
Network issues can cause duplicate deliveries. Use the delivery_id to deduplicate on your end.
Monitor the dashboard
If your endpoint goes to "paused" state, you'll stop receiving events. Check the dashboard and fix the issue before re-enabling.