Security-deposit API webhooks should update a booking from the current deposit record, not from an assumed sequence of messages. Verify the signature, preserve the booking-to-deposit mapping and retrieve authoritative state when an event could be stale or incomplete. A partial Stripe capture can be final even though the captured amount is smaller than the original hold.
This guide gives rental-software developers a state-mapping worksheet. For endpoint setup, use the Security Deposits API overview.
How should a security-deposit API webhook be verified?
PayRequest documents `X-PayRequest-Signature` as `sha256=` followed by the HMAC-SHA256 digest of the raw request body, using the configured webhook secret. Verify those original bytes before parsing or changing the body. Compare signatures with a suitable constant-time comparison and read the event name from `X-PayRequest-Event`.
The PayRequest reference lists the supported event names. Do not assume a Stripe signature header or timestamp scheme applies to PayRequest. Its public deposit page does not specify a delivery-order guarantee, event-ID schema or replay window; check the complete webhook contract before designing around those details.
Map events to booking decisions
A webhook is a notification about a deposit, not permission to charge for damage or hand over equipment. Keep the inspection, agreement and operator decision in your rental system.
| Notification or retrieved state | Booking interpretation | Operator or integration action |
|---|---|---|
| deposit.created / pending | Request exists; no confirmed hold | Await customer authorization |
| deposit.authorized | Funds were reserved | Retrieve state and capture_before before handover |
| deposit.captured | Capture completed | Record the actual captured amount and final state |
| deposit.partially_captured | Provider-specific partial outcome | Retrieve current state; do not infer another capture is possible |
| deposit.released | Authorization released | Close the hold record; avoid calling it a refund |
| deposit.expired | Confirmed hold is no longer capturable | Escalate any unresolved obligation |
| deposit.failed | Deposit operation failed | Inspect current record and failure context |
Store the latest API state alongside the booking ID and deposit ID. Keep payment status separate from booking cancellation, inspection completion and equipment return. These processes can happen at different times.
Why does a partial Stripe capture emit deposit.captured?
PayRequest's documented Stripe path supports one final capture. In the reference example, €350 is authorized, €150 is captured and €200 is released. The result is `captured`, with captured_amount of 150.00; it emits `deposit.captured`.
Your application must not calculate “€200 still secured” by subtracting the captured amount from the original amount. That remainder is released and unavailable for a second capture. The provider concept is explained in Stripe's authorization and capture documentation. For operator decisions, use the partial-capture guide.
How do you handle duplicates and delayed events?
Design your booking update so repeating the same notification does not repeat a customer message or capture action. Persist receipt and processing outcome, and use a documented delivery identifier if the contract supplies one. If it does not, do not invent a payload field: reconcile the current deposit and make the resulting business action idempotent in your own database.
As a design example, an authorized notification arrives after your local record already shows a final capture. Retrieve the deposit instead of moving the booking back to “funds reserved.” Stripe separately documents duplicate events and unordered delivery in its webhook guide; that guidance explains the general integration risk, without establishing PayRequest's retry schedule.
What should the customer see?
Show request pending, funds reserved, amount captured, released or expired using confirmed data. A processing or expired authorization attempt can still have API status pending with additional metadata; it is different from an expired previously confirmed hold.
Connect PayRequest security deposits to your booking record and retain rental-fee collection through payment links. Review account allowances and use the integration acceptance checklist before launch.
Editorial note: AI assisted with this article and cover. Public API documentation was reviewed on 13 October 2026; no webhook delivery or live capture was tested. The state worksheet is an original integration recommendation.


