---
title: "Pay Flight Booking Session"
method: POST
path: "/flight-booking/sessions/{session_id}/pay"
tags: ["flight-booking"]
---

# Pay Flight Booking Session

`POST /flight-booking/sessions/{session_id}/pay`

Charge and create a flight booking + operator task.

## Path parameters

- `session_id` string, uuid, required

## Request body

- FlightBookingPayRequest — Request body for POST /{session_id}/pay.
  - `payment_method_id` string, nullable — Stripe payment method ID (pm_xxx). If absent, returns client_secret for inline card entry.
  - `credit_amount_cents` integer, nullable — Axel credit to apply (cents). None/omitted=no credit, >0=apply this amount.
  - `payment_method_types` string[], nullable — How the deferred Stripe Elements group was configured, e.g. ['card'] (inline pay only). The PaymentIntent is created to match — Stripe rejects confirm on mismatch. Omitted = automatic payment methods.
  - `displayed_total_cents` integer, nullable — The pre-credit total the page showed at tap time, in cents. Compared with the server's pre-credit charge total; a difference refuses the pay (409 displayed_total_mismatch). Older builds send only this.
  - `displayed_charge_cents` integer, nullable — The number on the Pay button at tap time, in cents: the total AFTER the credit the page expected to apply. The customer's consent to an amount the server served: it never changes the charge, but when it differs from the amount this request would take after credit (a balance that shrank or vanished, a fare or hold that moved) nothing is charged and /pay answers 409 displayed_total_mismatch with every number (Sep 4 2026), after logging fare_hold_display_charge_mismatch and reporting to Sentry. Omitted: charged as computed.
  - `displayed_credit_cents` integer, nullable — The Axel credit the page expected to apply, in cents, so a refusal can say how the credit actually applied differed. Observed only.

## Response `200`

Successful Response

- FlightBookingPaymentResponse — Response from a successful flight booking payment. Two modes: - Saved card: all fields populated, status=completed. - Inline pay: client_secret returned, booking_id/reference_code/operator_task_id are None, status=awaiting_payment. Frontend confirms card, then calls confirm-payment.
  - `session_id` string, uuid, required
  - `booking_id` string, nullable
  - `reference_code` string, nullable
  - `operator_task_id` string, uuid, nullable
  - `payment_intent_id` string, required
  - `charged_amount_cents` integer, required
  - `currency` string, required
  - `status` 'active' | 'awaiting_payment' | 'processing' | 'completed' | 'failed' | 'abandoned' | 'manual_recovery_required', required
  - `client_secret` string, nullable
  - `credit_applied_cents` integer
  - `authorized_amount_cents` integer, nullable
  - `payment_status` string, nullable

## Other responses

- `409` — displayed_total_mismatch: the total the customer saw is not the total the server would charge; nothing was charged, review the new total and tap again. (Other 409s on this route keep their existing {message, error_code} shape.)
- `422` — Validation Error

## Changes

> 17 revisions in range; 1 not diffed.

- **2026-09-22** `b7b1f6448378` — 2 info
  - added the optional property `authorized_amount_cents` to the response with the `200` status
  - added the optional property `payment_status` to the response with the `200` status
- **2026-09-06** `fa0678aea849` — 4 info
  - added the new optional request property `displayed_charge_cents`
  - added the new optional request property `displayed_credit_cents`
  - added the new optional request property `displayed_total_cents`
  - added the non-success response with the status `409`

[Change history](https://skmtc.dev/helloaxel/apis/client-api-gateway/changes/flight-booking/sessions/:session_id/pay/post.md)

---

[API](https://skmtc.dev/helloaxel/apis/client-api-gateway.md) · [All operations](https://skmtc.dev/helloaxel/apis/client-api-gateway/llms.txt) · [OpenAPI document](https://skmtc.dev/helloaxel/apis/client-api-gateway/revisions/b7b1f6448378?raw)
