Preview Cancellation Refund
Preview the refund a customer would receive if a booking were cancelled right now. Returns the matched policy tier, refund amount, non-refundable fee, and a can_cancel flag โ exactly the same numbers the supplier portal Cancel modal renders.
This is a read-only endpoint. It runs no side effects (no refund, no booking update, no email). Use it to drive a confirm screen before calling DELETE /v1/bookings/{id}.
GET /v1/bookings/{id}/refund-preview
Authenticationโ
Requires a valid API key with bookings:read scope.
Path Parametersโ
| Parameter | Type | Description |
|---|---|---|
id | integer | Booking ID |
Request Exampleโ
curl -X GET "https://app.equipdash.com/api/v1/bookings/123/refund-preview" \
-H "Authorization: Bearer eqd_live_your_api_key"
Response (200 OK)โ
{
"data": {
"booking_id": 123,
"booking_reference": "RB-1042",
"can_cancel": true,
"cannot_cancel_reason": null,
"refund_note": null,
"policy": {
"id": 1,
"name": "Flexible",
"description": "Full refund up to 7 days before, 50% up to 24h before.",
"applies_to": "all-experiences",
"allow_cancellations": true,
"allow_reschedule": true,
"tiers": [
{ "id": 11, "applies_after_hours": 168, "human_threshold": "1 week", "refund_percentage": 100.0, "refund_method": "original_payment" },
{ "id": 12, "applies_after_hours": 24, "human_threshold": "1 day", "refund_percentage": 50.0, "refund_method": "original_payment" },
{ "id": 13, "applies_after_hours": 0, "human_threshold": "Within window", "refund_percentage": 0.0, "refund_method": "original_payment" }
],
"non_refundable_fee": 5.00,
"refund_method": "original_payment",
"currency": "USD"
},
"preview": {
"total_paid": 200.00,
"refund_percentage": 50.0,
"refund_amount": 95.00,
"non_refundable_fee": 5.00,
"refund_method": "original_payment",
"policy_has_tiers": true,
"matched_tier": {
"id": 12,
"applies_after_hours": 24,
"human_threshold": "1 day",
"refund_percentage": 50.0,
"refund_method": "original_payment"
}
}
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-04-22T11:00:00+00:00"
}
}
Response Fieldsโ
| Field | Type | Description |
|---|---|---|
booking_id | integer | The booking ID |
booking_reference | string|null | Customer-facing booking reference |
can_cancel | boolean | true when the booking's status is cancellable. The policy decides the refund, not whether staff may cancel. Start time is not a factor - see below. |
cannot_cancel_reason | string|null | Human-readable reason when can_cancel is false |
refund_note | string|null | Set when nothing is refunded automatically: no policy covers the booking, or its policy takes no cancellations. Show it beside the Cancel button. |
policy | object|null | The applicable policy (full shape โ same as GET /v1/settings/policies/{id}). null if no policy applies. |
preview.total_paid | number | Total amount paid against the booking |
preview.refund_percentage | number | The refund % that will run (matched tier % OR 0 when no tier matches OR legacy single % when policy has no tiers) |
preview.refund_amount | number | Net refund: total_paid ร refund_percentage โ non_refundable_fee, floored at 0 |
preview.non_refundable_fee | number | Per-policy fixed fee that will be deducted |
preview.refund_method | string | original_payment or store_credit |
preview.policy_has_tiers | boolean | true when the policy has at least one tier configured |
preview.matched_tier | object|null | The tier that ran. null when policy has no tiers OR cancellation missed every tier |
Cannot-cancel casesโ
can_cancel: false returns alongside:
"Cannot cancel a {status} booking"- booking is already cancelled / completed / returned
A booking no policy covers, or whose policy takes no cancellations, used to return can_cancel: false. It now returns can_cancel: true with a refund_note, and DELETE /v1/bookings/{id} cancels it with no automatic refund. Give money back afterwards with a refund if you want to.
The endpoint always returns 200 OK even when can_cancel is false โ it's an informational endpoint. Hit DELETE only when can_cancel: true.
Bookings that have already startedโ
A booking whose start time has passed still reports can_cancel: true, because DELETE /v1/bookings/{id} accepts it. An API key is a staff credential, and staff have to be able to close off a late call-in. A customer who never came is marked with Mark a No Show instead, which keeps the payment. The preview simply shows what that costs: the cancellation falls past every tier, so refund_percentage is 0, matched_tier is null, and refund_amount is 0 unless the policy is configured otherwise.
Start time used to force can_cancel: false with the reason "This booking has already started and can no longer be cancelled." It no longer does. If you disable a Cancel button on that reason string, the button now stays live.
Error Responsesโ
| Status | Code | Description |
|---|---|---|
| 401 | authentication_required | Missing or invalid API key |
| 403 | insufficient_scope | API key lacks bookings:read scope |
| 403 | forbidden | Booking belongs to another supplier |
| 404 | resource_not_found | Booking not found |