Make the next decision clearer.
- An event notification and the resulting business action are separate stages.
- Verify the original request body before trusting or processing an event.
- Assume a delivery can be repeated and make its effect safe to repeat.
- Acknowledge durable receipt quickly, then process and monitor the work.
What is a CRM webhook?
A CRM webhook is an HTTP notification sent to an endpoint you operate when a subscribed event occurs. For example, a record change can notify a reporting service that there is new work to process. The receiver decides what that event means for its workflow. The notification itself does not guarantee that a report has already been updated.
Compare it with polling: a polling worker asks for information on a schedule; a webhook sender initiates the notification. Events can reduce unnecessary checks, but you still need an initial state, recovery and a way to detect missed work. A webhook and an API usually serve complementary purposes.
Choose the narrowest event subscription that supports the task. A consumer that only needs selected record changes should not take responsibility for every event merely because a broad subscription is available. Document which event types it understands and what happens when a new or unsupported type arrives.
Separate receipt, processing and business completion
Treat the receiver as a durable handoff. It verifies the request, records a unique event and queues the necessary work. Only after that durable step should it acknowledge successful receipt. A background worker can then make the slower external calls. If the process crashes after an early acknowledgement but before saving the event, the sender may reasonably consider its job complete while your work disappears.
GitHub recommends asynchronous processing so webhook endpoints respond promptly, and Stripe similarly recommends returning a successful response before slow downstream processing [1][2]. The important boundary is not “respond before doing anything”; it is “complete the required verification and durable acceptance before acknowledging”.
Track at least three distinct states: received, applied and failed. “Delivered” in the sender’s dashboard only proves the receiver acknowledged the request. Your operator should be able to trace the event ID to the destination change or a specific unresolved error.
One event. Two completion boundaries.
- 01Verify
Check signature, timestamp and workspace.
- 02Accept
Persist event identity and queued work.
- 03Acknowledge
Return 2xx after durable acceptance.
- 04Apply
Worker completes and records the effect.
Verify the exact bytes and the sender’s signature
A public endpoint will receive requests from the internet. Do not trust a request because it contains a plausible event name or your workspace ID. Use the provider’s documented signature verification process, its current secret and the exact request bytes. Stripe explicitly requires the unmodified raw body for verification [2].
Meibo sends X-Meibo-Signature with t=<timestamp>,v1=<hex digest>. The digest is HMAC-SHA256 over the timestamp, a full stop and the original JSON body. The payload includes id, type, workspace_id, created_at and data; X-Meibo-Event-Id also carries the event identifier [3].
Verify with a constant-time digest comparison after checking lengths and format. Define an acceptable timestamp window and keep server clocks accurate to limit replay of old requests. Confirm the workspace and event type are allowed. Parse and process the payload only after the signature check; parsing and reserialising JSON before verification can change the bytes.
X-Meibo-Signature: t=<unix-seconds>,v1=<hex-digest>
signed_message = timestamp + "." + raw_request_body
hex_digest = HMAC_SHA256(webhook_secret, signed_message)
Event identity: payload.id / X-Meibo-Event-IdMake duplicate deliveries harmless
The sender may retry if an acknowledgement is lost, even when the receiver already accepted the event. Store event identity in durable storage with a uniqueness constraint scoped to the sender and workspace. A process-local set is not enough: it disappears on restart and is not shared by separate server instances.
The deduplication decision and acceptance of the work need a reliable boundary. One design inserts the event and an internal job in the same database transaction. A repeated, already accepted event can then receive a successful acknowledgement without creating another job. If a previous attempt rolled back, the next delivery should still be able to accept it.
The worker also needs safe effects. A single queued job can run twice after a crash. When calling another service, use its documented idempotency mechanism or a destination identity that lets you recognise an already completed operation. Receiving an event once does not imply every downstream side effect occurs exactly once.
A repeated event should converge on the same work
- 01First delivery
Insert the unique event and its job.
- 02Lost response
Sender cannot confirm receipt.
- 03Repeated delivery
Recognise the already accepted event.
- 04Same outcome
Acknowledge; avoid creating a second job.
Do not assume events arrive in business order
Consider an opportunity moving from “Review” to “Won” while delivery of the earlier change is delayed. If the consumer blindly applies event bodies in arrival order, it may restore the old state after processing the new one. Decide whether an event is a historical fact to retain or a prompt to fetch current state. Those uses require different handling.
For a current-state mirror, fetching the latest record can be safer than treating every event payload as the final truth. Where the source provides reliable versions or sequence numbers, use them according to its contract. A timestamp alone should not be treated as a universal ordering guarantee.
Meibo’s delivery implementation does not establish a strict ordering guarantee. Design consumers accordingly. For deleted records, define the meaning of an absent record and preserve enough identity to avoid recreating it during the next reconciliation. Keep destructive effects subject to the same ownership rules as ordinary updates [3].
Know the delivery limits and build a recovery route
Meibo uses a five-second outbound request timeout and treats a 2xx response as delivered. Failed attempts are rescheduled with backoff; the current delivery implementation limits attempts to eight. Those are product-specific limits, not a guarantee that every external job completes within a particular time [3].
If your receiver is unavailable longer than the retry window, recovery needs an operator or a supported replay mechanism. Do not assume events will be retried forever. Keep a failure view, a named owner and a documented way to reconcile affected records. A replay must retain the original business event identity even if delivery metadata changes.
Monitor backlog age and unresolved failures, not just the total number of requests. A thousand healthy deliveries can hide one important failed handoff. For an incident, record the affected time range, event types, destination actions and reconciliation result before declaring the connection recovered.
Test the receiver’s awkward moments
Start with one valid signed request, then alter a body byte without regenerating the signature. The modified request should be rejected. Test a wrong secret, a stale timestamp and an unexpected workspace. Keep test secrets separate from production and exclude payloads containing customer information from public debugging tools.
Next, deliver the same event twice, restart the receiver between deliveries and run two deliveries concurrently. Verify one durable unit of business work results. Simulate a destination timeout after a successful write and prove the worker can recover without producing a second side effect.
Finally, delay an older event, interrupt processing after receipt and exercise the failed-job recovery path. Use the downloadable checklist to capture evidence. The goal is a traceable outcome under failure, not a receiver that only works when requests arrive once and in order.
Webhook delivery test plan.
Exercise signatures, duplicate events, restarts, delayed delivery and failed processing. Keep an evidence trail for each recovery path.
Download CSVOpens in spreadsheet software. Planning worksheet, not a direct CRM import file. All example rows are illustrative.Common questions.
Are webhooks the same as an API?+
No. An API lets your application request an operation; a webhook notifies your endpoint about an event. A workflow commonly receives an event and then uses an API to fetch or change information.
Why did I receive the same webhook twice?+
A sender may retry when it does not receive a successful acknowledgement, including when the first acknowledgement was lost. Design durable deduplication around the business event identity.
Should I return 200 before processing the event?+
Return a success response after verifying and durably accepting the event or confirming it was already accepted. Slow business processing can follow asynchronously; acknowledging before durable acceptance risks losing work.
Can I verify a signature after parsing JSON?+
Use the original request bytes as required by the sender’s signing contract. Parsing and reserialising can change whitespace or field order and invalidate verification.
Does a delivered webhook mean the destination was updated?+
It means the receiver acknowledged the delivery. Track downstream processing separately and reconcile the actual business result.
What happens when all retry attempts fail?+
That depends on the provider. Maintain a failure queue and a documented replay or reconciliation procedure; do not rely on unlimited automatic retries.
Sources & methodology.
Meibo’s recommended framework, with primary documentation for the specific product facts cited above. This is AI-assisted editorial content. Examples, diagrams and calculations are illustrative; they are not customer results or independent research findings.
- GitHub Docs — Best practices for using webhooks
Primary guidance on event subscriptions, secrets, delivery identifiers and asynchronous handling.
- Stripe Docs — Receive Stripe events
Primary guidance on raw-body signature verification and prompt acknowledgements. Stripe-specific timing and delivery behaviour is not attributed to Meibo.
- Meibo developer documentation
The Meibo-specific contract. Examples were checked against the API and webhook implementation; they are not a claim that every external integration has been deployed or verified.
Sources checked 7 October 2026. Read the editorial policy or suggest a correction.