/api/v1/bookings/{id}/cancelCancels a booking and runs the organization's cancellation flow: refund according to the chosen mode, cancellation email to the guest, notice to staff. Cancelling an already cancelled booking is not an error — it answers 200 with the unchanged booking, so a retry is always safe. Requires the "bookings:write" scope and an "Idempotency-Key" header.
Path parameters#
| Field | Type | Description |
|---|---|---|
idrequired | string | Awrora id (UUID) for the booking. |
Headers#
| Field | Type | Description |
|---|---|---|
Idempotency-Keyrequired | string≥ 8 chars · ≤ 200 chars | A unique key for this request, 8-200 characters (a UUID is a good choice). Retrying with the same key replays the first response verbatim — same status, same body, plus "Idempotent-Replayed: true" — instead of acting twice. Reusing a key with a different body answers 422. |
Request body#
| Field | Type | Description |
|---|---|---|
refund | stringdefault "auto" | How to handle money already taken. "auto" (default) follows the organization's refund policy, the same way the admin cancel button does. "none" keeps the money. Bookings without a card payment are unaffected either way. "auto""none" |
reason | string≤ 200 chars | Why it was cancelled. Stored with the cancellation for staff to read. |
Example request#
bash
curl -X POST "https://your-site.awrora.app/api/v1/bookings/id_8f2k3n/cancel" \
-H "Authorization: Bearer $AWRORA_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"refund": "auto",
"reason": "string"
}'Responses#
200The booking, now cancelled.400Invalid request — codes "validation_failed" or, on an endpoint that requires one, "idempotency_key_required".401Missing, invalid, revoked or expired API key — codes "api_key_missing", "api_key_invalid", "api_key_revoked", "api_key_expired".403The API app is off, the plan does not include the API, or the key lacks the required scope — codes "app_not_enabled", "plan_upgrade_required", "insufficient_scope" (the last carries "required_scope").404No such resource. The same response is returned for a resource that belongs to another organization — code "not_found".422The request was understood but cannot be fulfilled as asked — codes "validation_failed" or "idempotency_key_reused" (the same Idempotency-Key was already used with a different body).429Rate limit exceeded — code "rate_limited". See the x-ratelimit-* headers.500Something went wrong on our side — code "internal_error".
Response 200
| Field | Type | Description |
|---|---|---|
idrequired | string | Awrora id (UUID) for the booking. |
booking_numberrequired | integer | null | Sequential booking number within the organization, or null for legacy rows. |
statusrequired | string | pending = created, awaiting payment; confirmed = active; cancelled = cancelled. "pending""confirmed""cancelled" |
sourcerequired | string | null | Where the booking came from: online, admin, agency, ai or api. |
created_atrequired | string | ISO 8601 timestamp with offset. |
updated_atrequired | string | ISO 8601 timestamp with offset. |
experiencerequired | object | The experience that was booked. |
departurerequired | object | The departure that was booked. |
customerrequired | object | The guest details captured at checkout. Not the customer record — see /v1/customers. |
guestsrequired | object[] | Guest lines. May be empty for legacy rows. |
add_onsrequired | object[] | Add-on lines. Empty when none were bought. |
totalsrequired | object | Money totals for the booking. |
paymentrequired | object | How the booking is paid, and where that payment stands. |
noterequired | string | null | Free-text note from the buyer or staff, or null. |
manage_urlrequired | string | null | Link where the guest can open and finish their own booking. Only returned to keys with the "bookings:write" scope — read-only keys and webhook/event payloads always get null, because anyone holding the link can see the booking and complete it. Also null when no valid link exists (no token, or the token has expired). Treat it as a secret. |
200 response
{
"id": "res_8f2k3n",
"booking_number": -9007199254740991,
"status": "pending",
"source": "string",
"created_at": "string",
"updated_at": "string",
"experience": {
"id": "res_8f2k3n",
"title": "string",
"slug": "string"
},
"departure": {
"id": "res_8f2k3n",
"starts_at": "string",
"ends_at": "string"
},
"customer": {
"name": "string",
"email": "anna@example.com",
"phone": "string"
},
"guests": [
{
"tier_id": "tier_8f2k3n",
"tier_label": "string",
"count": -9007199254740991,
"unit_price": {
"amount_minor": -9007199254740991,
"currency": "SEK"
}
}
],
"add_ons": [
{
"id": "res_8f2k3n",
"label": "string",
"count": -9007199254740991,
"unit_price": {
"amount_minor": -9007199254740991,
"currency": "SEK"
}
}
],
"totals": {
"subtotal": {
"amount_minor": -9007199254740991,
"currency": "SEK"
},
"discount": {
"amount_minor": -9007199254740991,
"currency": "SEK"
},
"gift_card": {
"amount_minor": -9007199254740991,
"currency": "SEK"
},
"total": {
"amount_minor": -9007199254740991,
"currency": "SEK"
}
},
"payment": {
"method": "string",
"source": "stripe",
"status": "paid"
},
"note": "string",
"manage_url": "https://example.com/webhooks/awrora"
}