---
title: "Cancel Booking"
method: POST
path: "/api/booking/{order_id}/cancel"
tags: ["booking"]
---

# Cancel Booking

`POST /api/booking/{order_id}/cancel`

## Request

- Base URL: `https://api.pointifytravels.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.pointifytravels.com/api/booking/{order_id}/cancel`
- Auth: none declared

Cancel a Duffel order. Backend-only — apps/web checks ownership.

This used to depend on ``require_auth``, which was wrong in both
directions at once.

TOO WEAK: ``require_auth`` proves someone is signed in, not that the
booking is theirs, and ``order_id`` goes straight to Duffel. Since
``InternalAuthMiddleware`` admits any verified Supabase JWT, any account
holder with an order id could cancel that booking. Ownership cannot be
checked here — ``bookings`` lives in the WEB database, which this service
reaches only when ``WEB_DATABASE_URL`` is provisioned, so a check here
would fail closed on every cancellation whenever it isn't.

TOO STRONG: the only real caller is apps/web, which proxies with
``X-Internal-Key`` and no ``Authorization`` header, so ``require_auth``
rejected the one caller meant to get through.

The ownership gate therefore lives at the web layer, which has the user's
session and an RLS-scoped view of ``bookings``; this route only has to
establish that the request came from our own backend.

## Path parameters

- `order_id` string, required

## Response `200`

Successful Response

- unknown

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/pointifytravels/apis/pointify-deal-engine.md) · [All operations](https://skmtc.dev/pointifytravels/apis/pointify-deal-engine/llms.txt) · [OpenAPI document](https://skmtc.dev/pointifytravels/apis/pointify-deal-engine/revisions/4350142a4216?raw)
