Using webhooks, you can receive an HTTPS notification when your audits and journeys finish running. To use a webhook, you’ll need a web server on the internet that can receive HTTPS requests. ObservePoint can send a JSON payload to any HTTPS URL that you configure.
Each audit and journey can be configured to send a webhook request on completion. Webhook configuration is optional.
You have two options for configuring ObservePoint webhooks:
When you create a new audit or journey using a POST request, you can specify a webhook URL in the webHookUrl field.
POST https://api.observepoint.com/v2/web-audits
POST https://api.observepoint.com/v2/web-journeysFor existing audits or journeys, you can assign a webhook URL using the webHookUrl field in your PUT payload to these API endpoints:
PUT https://api.observepoint.com/v2/web-audits/{auditId}
PUT https://api.observepoint.com/v2/web-journeys/{journeyId}At app.observepoint.com, log in and navigate to the Data Sources page. Click the Edit button on any audit or journey, enter the webhook URL, and click Save.

Upon completion of an audit or journey, ObservePoint sends the following POST payload to the specified URL. The webhook is sent whether the run is successful or not.
{
"itemId": 12345,
"itemType": "audit", // or "web-journey"
"runId": 98765
}| Field Name | Description |
|---|---|
itemId | The ID of the audit or journey. |
runId | The run ID of the completed audit or journey. |
itemType | Indicates whether the run is an "audit" or "web-journey". |
When you receive a webhook request, you can query the ObservePoint API to download results using the itemId and runId.
The following are some common use cases for webhooks:
- Check for unapproved cookies or tags and record them in an issue tracker, like Jira
- Trigger a script to pull the page details report and email the results to recipients listed in the notifications field.
- Ingest results into a BI system such as Tableau by triggering a data import when an audit or journey completes.
- Integrate with Teams or Slack: trigger a message to your Teams or Slack channel notifying of rule failures.
To enhance webhook security, ObservePoint signs every webhook request with a unique secret key tied to your account. This allows you to verify that incoming webhook requests are genuine and have not been tampered with.
Before you can verify webhook signatures, you must generate a signing secret for your account. You must have Admin permissions to perform this action.
Please refer to our getting started documentation to learn how to make that request.
Endpoint
POST https://api.observepoint.com/v3/webhooks/rotate-secretResponse
{
"sharedSecret": "string",
"accountId": number
}The sharedSecret is shown only once. Be sure to store it securely, as it cannot be retrieved again. You can generate a new secret at any time by calling the same endpoint.
Invoking this endpoint again will immediately rotate the webhook signing secret for your entire account. Once rotated, all future webhook requests will use the new secret. Any systems or services that verify webhook signatures must be updated with the new secret right away, or verification will fail until they do.
Each webhook request sent by ObservePoint includes a signature header that contains both the timestamp and the generated signature.
| Header Name | Example Value |
|---|---|
ObservePoint-Signature | t=1693325764,sigv1=3eae1baf0f7f9ed8f9db7e88f27c2f3f3fbb0a73e839b6e10b0d8bb1a71a449d |
The signature is computed using an HMAC SHA-256 signature of a canonical payload that combines the timestamp and the raw webhook body.
To verify the webhook:
- Extract the timestamp (
t) and signature (sigv1) from theObservePoint-Signatureheader. - Concatenate the timestamp, a period (
.), and the raw webhook payload body. - Compute an HMAC SHA-256 signature using your stored
sharedSecret. - Compare your computed signature to the value of
sigv1.
If they match, the webhook is verified.
The following code samples show how to verify the webhook signature.
If you want to test these code samples, you can use the following test values:
| Parameter | Example Value | Description |
|---|---|---|
secret | epFiUaBZdFbRGn7+8v4LD4n0l3VxbTvxwnj3UMpgrlg== | An example signing secret key returned by POST https://api.observepoint.com/v3/webhooks/rotate-secret |
raw_body | {"runId":873230,"itemType":"web-journey","itemId":748316} | An example webhook body used to compute the signature |
header_value | t=1760064757,sigv1=00gNS2RGUZJrOBiHwgGJm9Zb1oDRPsVjt5F1NhmVIzc= | An example ObservePoint-Signature header value sent with the webhook |
import re, hmac, hashlib, base64
def verify_observepoint_webhook(secret: str, webhook_body: str, header_value: str) -> bool:
"""
Verify the ObservePoint webhook signature using HMAC-SHA256.
Args:
secret (str): The signing secret returned by https://api.observepoint.com/v3/webhooks/rotate-secret
webhook_body (str): The exact request body string. Example: '{"runId":873230,"itemType":"web-journey","itemId":748316}'
header_value (str): The value of the ObservePoint-Signature header. Example: 't=1234567890,sigv1=ABC123...'
Returns:
bool: True if the signature is valid, False otherwise.
"""
header_match = re.search(r't=(\d+),sigv1=([^,$]+)', header_value)
if header_match:
header_timestamp = header_match.group(1)
header_signature = header_match.group(2)
else:
raise ValueError(f'Invalid signature header: {header_value}')
key = base64.b64decode(secret)
to_sign = f"{header_timestamp}.{webhook_body}".encode('utf-8')
calculated_signature_bytes = hmac.new(key, to_sign, hashlib.sha256).digest()
header_signature_bytes = base64.b64decode(header_signature)
return hmac.compare_digest(calculated_signature_bytes, header_signature_bytes)import crypto from 'crypto';
/**
* Verify the ObservePoint webhook signature using HMAC-SHA256.
*
* @param {string} secret - The signing secret returned by https://api.observepoint.com/v3/webhooks/rotate-secret
* @param {string} webhookBody - The exact request body string. Example: '{"runId":873230,"itemType":"web-journey","itemId":748316}'
* @param {string} headerValue - The value of the ObservePoint-Signature header. Example: 't=1234567890,sigv1=ABC123...'
* @returns {boolean} true if the signature is valid, false otherwise
*/
function verifyObservepointWebhook(secret, webhookBody, headerValue) {
const headerMatch = headerValue.match(/t=(\d+),sigv1=([^,$]+)/);
if (!headerMatch) {
throw new Error(`Invalid signature header: ${headerValue}`);
}
const headerTimestamp = headerMatch[1];
const headerSignature = headerMatch[2];
const key = Buffer.from(secret, 'base64');
const toSign = `${headerTimestamp}.${webhookBody}`;
const calculatedSignature = crypto
.createHmac('sha256', key)
.update(toSign, 'utf8')
.digest();
const headerSignatureBytes = Buffer.from(headerSignature, 'base64');
return calculatedSignature.length === headerSignatureBytes.length &&
crypto.timingSafeEqual(calculatedSignature, headerSignatureBytes);
}If the header signature does not match your computed signature, you should reject the webhook request by responding with a 403 status code (or other error status code).
When it’s time to rotate your webhook signing secret, whether for routine security maintenance or after an incident, you can generate a new secret using the Generate Your Webhook Signing Secret section above.
Rotating the secret immediately replaces the existing signing secret for your entire account. Any subsequent webhook requests will be signed using the new secret.
To safely rotate your secret:
- Generate and store the new secret securely.
- Update all receiving services (such as your webhook consumer, middleware, or verification scripts) to use the new secret.
- Verify webhook delivery using the new signature to ensure your systems are properly configured.
Once a new secret is generated, the old secret stops being used immediately. Webhooks signed with the new secret will not validate against the old one.