A webhook is a way for one application to automatically send information to another application when a specific event occurs.
Instead of repeatedly checking for updates, a webhook allows systems to communicate in real time. When an event occurs, such as an order being created, a payment being completed, or a service being provisioned, the system sends an HTTP request with event data to a URL you specify.
This approach enables you to automate workflows, synchronize data between systems, and respond to events in real time without manual intervention.
For example, you can configure a webhook to notify your application whenever a new IP address is provisioned. When the event occurs, our platform sends the event details to your webhook URL, allowing your application to automatically update records, trigger workflows, or notify team members.
You can create, manage, and monitor webhooks from the Webhooks page within your company profile.
To create a new webhook:
After the webhook has been created, the system will generate and display a Webhook Secret. This secret is used to verify that incoming webhook requests originate from Priority Prospect.
Keep your webhook secret secure and do not share it publicly.
From the Webhooks page, you can:
Each webhook includes a log history that allows you to review delivery attempts and troubleshoot issues.
Webhook logs contain information such as:
Reviewing webhook logs can help identify configuration issues, endpoint errors, or failed deliveries.
Webhooks can be triggered by a variety of events that occur within the platform. When a subscribed event occurs, a notification is automatically sent to your configured webhook endpoint.
| domain.created | Triggered when a domain is created. |
| domain.deleted | Triggered when a domain is deleted. |
| domain.changed_ip_address | Triggered when a domain's primary IP address is changed. |
| domain.updated_additional_ip_addresses | Triggered when additional IP addresses assigned to a domain are updated. |
| domain.updated_hosting_account | Triggered when a domain is assigned to a different hosting account. |
| domain.ssl_installed | Triggered when an SSL certificate is installed for a domain. |
| domain.ssl_renewed | Triggered when an SSL certificate is renewed. |
| domain.ssl_uninstalled | Triggered when an SSL certificate is removed from a domain. |
| email_address.created | Triggered when an email address is created. |
| email_address.deleted | Triggered when an email address is deleted. |
| ip_address.updated | Triggered when an IP address configuration is updated. |
| shared_hosting.account_created | Triggered when a shared hosting account is created. |
| invoice.created | Triggered when a new invoice is generated. |
| invoice.payment_received | Triggered when payment is received for an invoice. |
| order.suspended | Triggered when an order is suspended. |
| order.unsuspended | Triggered when an order is reactivated after suspension. |
| software.installed | Triggered when software is installed. |
| software.updated | Triggered when software is updated (automatic updates are enabled/disabled). |
| software.uninstalled | Triggered when software is removed. |
| software.cloned | Triggered when software is cloned. |
| software.imported | Triggered when software is imported (from your cPanel hosting account). |
| software.migrated | Triggered when software is migrated (from an external host). |
New webhook events may be added over time as new features and services become available. The most up-to-date list of events can always be found when creating or editing a webhook.
Each webhook event includes a JSON payload containing information about the event that occurred.
The exact structure of the payload depends on the event type. For example, a domain-related event will contain different information than an invoice or software-related event.
Because payload structures may evolve as new features and fields are added, we maintain the authoritative payload specifications in our API documentation.
Visit our API documentation: https://api.priorityprospect.com/docs/
Every webhook request is signed using your webhook secret. Verifying the signature ensures that:
The request was sent by our platform.
The request payload was not modified in transit.
Every webhook request includes the following headers:
X-Webhook-Timestamp: <timestamp>
X-Webhook-Signature: sha256=<signature>
X-Webhook-Delivery-Id: <delivery-id>
X-Webhook-Event: <event-key>
X-Webhook-Id: <webhook-id>
The webhook signature is generated using HMAC-SHA256 over the following string:
<timestamp>.<raw request body>
Use your webhook secret as the HMAC key.
Read the X-Webhook-Timestamp header.
Read the X-Webhook-Signature header.
Read the raw request body exactly as received.
Generate an HMAC-SHA256 signature using:
<timestamp>.<raw request body>
Prefix the generated hash with sha256=.
Compare the generated signature with the value from X-Webhook-Signature using a constant-time comparison function.
Reject the request if the signatures do not match.
Important: Verify the signature using the raw request body before parsing JSON. Parsing and re-serializing JSON can change whitespace, formatting, or key order and cause signature verification to fail.
$secret = 'your_webhook_secret';
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$body = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac(
'sha256',
$timestamp . '.' . $body,
$secret
);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit;
}
import hashlib
import hmac
secret = "your_webhook_secret"
timestamp = request.headers["X-Webhook-Timestamp"]
signature = request.headers["X-Webhook-Signature"]
body = request.get_data() # Raw request body (Flask example)
expected = "sha256=" + hmac.new(
secret.encode(),
timestamp.encode() + b"." + body,
hashlib.sha256,
).hexdigest()
if not hmac.compare_digest(expected, signature):
return "", 401
import crypto from "crypto";
const secret = "your_webhook_secret";
const timestamp = req.headers["x-webhook-timestamp"];
const signature = req.headers["x-webhook-signature"];
const body = req.rawBody; // Raw Buffer
const expected =
"sha256=" +
crypto
.createHmac("sha256", secret)
.update(Buffer.concat([
Buffer.from(timestamp),
Buffer.from("."),
body,
]))
.digest("hex");
if (
!crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
)
) {
return res.sendStatus(401);
}
In addition to verifying the signature, we recommend validating the timestamp to prevent replay attacks.
For example, reject requests whose timestamp differs from the current time by more than 5 minutes.
current_time - webhook_timestamp > 300 seconds
Choose a time window that matches your application's security requirements.
Using a parsed or re-serialized JSON payload instead of the raw request body.
Using the wrong webhook secret.
Omitting the timestamp when generating the signature.
Modifying the request body before verification.
Comparing signatures with a non-constant-time comparison function.
Allowing middleware, proxies, or frameworks to alter the request body before verification.
If signature verification consistently fails:
Verify that the webhook secret matches the endpoint that received the webhook.
Log the received timestamp and signature headers.
Confirm that the raw request body is being used.
Verify that the generated signature includes:
<timestamp>.<raw request body>
Check whether any middleware modifies the request body before your application receives it.
Confirm that the generated signature includes the sha256= prefix.