Webhooks notify your system in real-time when events occur on our platform. Instead of polling for updates, your application receives instant notifications when orders are placed, domains are registered, mailboxes are created, and subscriptions change. This allows you to automatically sync data, provision user accounts, and handle failures gracefully.
Event Lifecycles#
Our platform generates webhooks through three distinct lifecycles. Each workflow has success and failure paths.1. Normal Order Lifecycle (Domain + Mailboxes)#
When a user places an order for both a domain and mailbox accounts:Step 1: Domain RegistrationYour order triggers domain provisioning with the registrar
You receive either domain.order.success or domain.order.failed
Step 2: Mailbox Creation (only if domain succeeds)If domain succeeded, mailbox accounts are provisioned at Google/Microsoft
You receive either mailbox.order.success or mailbox.order.failed
If domain failed, this step is skipped — no mailbox events are sent
Step 3: Individual Mailbox Ready NotificationsFor each mailbox successfully created, you receive mailbox.created
This event fires once per mailbox with full credentials and account details
If you ordered 3 mailboxes and all succeed, you get 3 separate mailbox.created events
Whenever a user modifies mailbox details (first name, profile picture, etc.), you receive mailbox.updated
Order placed
↓
domain.order.success ✓
↓
mailbox.order.success ✓
↓
mailbox.created (mailbox 1)
mailbox.created (mailbox 2)
mailbox.created (mailbox 3)
↓
(Later, if user updates details)
mailbox.updated
Order placed
↓
domain.order.failed ✗
↓
(No mailbox events sent)
2. Subscription Lifecycle (Renewal & Cancellation)#
Mailbox subscriptions follow their own lifecycle separate from domain registration.When the subscription renewal period arrives (based on the subscription term)
The system attempts to renew for the next period
subscription.renewal.success — Subscription successfully renewed
subscription.renewal.failed — Renewal blocked. Usually because the linked domain is in GRACE_PERIOD or EXPIRED
If a user disables auto-renewal and the current period ends, you receive subscription.cancelled
This indicates the mailbox accounts will no longer be available after the current term
Event sequence example (successful renewal):Subscription period ends
↓
Renewal period begins
↓
subscription.renewal.success ✓
↓
Next period active
Event sequence example (failed renewal):Subscription period ends
↓
Renewal period begins
↓
subscription.renewal.failed ✗
(Reason: domain is in GRACE_PERIOD or EXPIRED)
↓
User must renew domain at registrar before subscription can renew
Event sequence example (cancellation):User disables auto-renewal
↓
Current period expires
↓
subscription.cancelled ✗
↓
Mailboxes no longer available
3. Pre-Warmed Mailboxes Lifecycle#
Pre-warmed mailboxes are a specialized product — accounts that are pre-created and "warmed up" to improve deliverability.User orders pre-warmed mailbox accounts
The system allocates pre-warmed accounts from the available pool
This is faster than creating new accounts from scratch
prewarmup.order.success — Accounts assigned immediately with full credentials
prewarmup.order.failed — Assignment failed (no pool available, insufficient wallet balance, or domain restrictions)
Important: A single order may include multiple domains. Some domains can succeed while others fail, resulting in both prewarmup.order.success and prewarmup.order.failed being triggered for the same order. Check the domain field in each event to identify which domains succeeded or failed.Pre-warmup order placed
↓
prewarmup.order.success ✓
↓
Mailboxes assigned and ready to use
(User receives credentials immediately)
Event sequence example (with multiple domains):Order placed for domain-a.com + domain-b.com
↓
prewarmup.order.success (domain-a.com) ✓
prewarmup.order.failed (domain-b.com) ✗
↓
domain-a.com mailboxes available
domain-b.com assignment failed
Getting Started#
Step 1: Create a webhook endpoint#
Create a POST endpoint on your server that accepts webhook requests:POST https://your-domain.com/webhooks
Verify the request signature
Respond with 200 OK to acknowledge receipt
Handle asynchronously for long-running operations
Step 2: Subscribe to events#
1.
Go to Settings → Webhooks
3.
Select which events you want to receive
4.
Copy your API key (used for signature verification)
Step 3: Verify webhook signatures#
Every webhook request includes two security headers:cmr-x-signature — HMAC-SHA256 signature of the payload
cmr-x-timestamp — Unix timestamp when the request was sent
Verify both before trusting the webhook:Step 4: Implement idempotency#
Webhooks may be retried if your endpoint doesn't respond with 200 OK. Always store the eventId and skip duplicate processing:
Webhook Structure#
All webhooks follow the same structure:{
"event": "domain.order.success",
"eventId": "6SSHBXWR3N4JEKGRQSG3KW3D76N6",
"data": {
"userId": "PWM7Y25RYZ450YNM8K8FX9GK5AHX",
"userEmail": "johndoe@company.com",
"orderId": "NQ682GAVFTMYC2H6C87PPKPG5WXV",
...event-specific fields...
}
}
event — Type of event (e.g., domain.order.success)
eventId — Unique identifier for this webhook event (use for deduplication)
data — Event-specific payload with details
Event Reference#
| Event | Lifecycle | Triggered when | Retry? |
|---|
domain.order.success | Normal order | Domain successfully registered | No |
domain.order.failed | Normal order | Domain registration failed | No |
mailbox.order.success | Normal order | Mailbox provisioning succeeded | No |
mailbox.order.failed | Normal order | Mailbox provisioning failed | No |
mailbox.created | Normal order | Individual mailbox is ready | No |
mailbox.updated | Normal order | User updates mailbox details | No |
subscription.renewal.success | Subscription | Subscription renewed successfully | No |
subscription.renewal.failed | Subscription | Renewal blocked by domain status | No |
subscription.cancelled | Subscription | User cancels auto-renewal | No |
prewarmup.order.success | Pre-warmup | Pre-warmed accounts assigned | No |
prewarmup.order.failed | Pre-warmup | Pre-warmup assignment failed | No |
Best Practices#
1. Respond quickly#
Respond with 200 OK immediately after receiving the webhook. Process asynchronously in the background:2. Store the eventId#
Always persist eventId in your database to prevent duplicate processing:3. Log everything#
Log all incoming webhooks with timestamps and outcomes for debugging:4. Handle retries gracefully#
We retry failed webhooks up to 3 times. The same eventId may arrive multiple times. Your idempotency check prevents duplicate processing automatically.5. Set appropriate timeouts#
Your endpoint must respond within 60 seconds. If processing will take longer, queue it:6. Validate data, don't assume#
Always validate that expected fields exist in the payload:
Security & Reliability#
Signature Verification#
Every webhook is cryptographically signed using HMAC-SHA256. The signature is included in the cmr-x-signature header. Always verify this before processing.Why: This proves the webhook came from us and wasn't tampered with.Replay Protection#
The cmr-x-timestamp header contains the Unix timestamp when we sent the webhook. Reject any request older than 5 minutes.Why: This prevents attackers from replaying old webhooks.Retry Policy#
If your endpoint returns a non-2xx response, we automatically retry:Attempt 2: After 30 seconds
Attempt 3: After 5 minutes
After 3 attempts, the webhook is marked failed. You can retry manually from the dashboard.Rate Limiting#
We send webhooks at a controlled rate. No rate limits are enforced on your end, but webhook delivery is throttled to prevent overwhelming your service.
Common Issues & Troubleshooting#
Not receiving webhooks?#
Check 1: Is your endpoint publicly accessible?Check 2: Verify signature verification isn't rejecting valid webhooksTemporarily log the computed signature vs. received signature
Ensure you're using the correct API key
Check 3: Check the webhook logs in admin dashboardLook for failed delivery attempts
Receiving duplicate events?#
This is expected! Both success and failure scenarios can produce duplicates due to retries. Always implement idempotency checks using eventId.
Next Steps#
Learn the details of each event type:
Support#
If you have any questions or need further assistance, please contact our support team. Modified at 2026-04-03 08:37:09