Skip to content

Bookings & Payments

Booking Flow

User browses activity → Clicks "Book Now"


Booking form (date, group size) → POST /bookings


Booking created (status: PENDING_PAYMENT)


POST /stripe/create-checkout-session → Stripe Checkout URL


User completes payment on Stripe


Stripe webhook → POST /stripe/webhook
    (checkout.session.completed)


Prisma transaction:
  - Booking status → CONFIRMED
  - Payment record → SUCCESS
  - Activity.bookingsCount + 1

Endpoints

MethodEndpointAuthDescription
GET/bookingsUserUser's bookings
GET/bookings/:idUserSingle booking detail
POST/bookingsUserCreate booking
PATCH/bookings/cancel/:idUserCancel booking
POST/stripe/create-checkout-sessionUserCreate Stripe Checkout
POST/stripe/webhookPublic (Stripe)Stripe webhook handler

Create Booking

POST /api/v1/bookings
Body: {
  activityId: number,
  startDate: string (ISO date),
  days: number,
  groupSize: number
}
Response: { booking: { id, status: "PENDING_PAYMENT", totalPrice } }

Creates a booking with PENDING_PAYMENT status and calculates totalPrice based on the activity's price × groupSize × days.

Create Stripe Checkout

POST /api/v1/stripe/create-checkout-session
Body: {
  activityId: number,
  startDate: string,
  days: number,
  groupSize: number,
  bookingId: number
}
Response: { sessionUrl: string }

Creates a Stripe Checkout Session and returns the URL for redirect. The session includes:

  • Line item with activity title, price, quantity
  • bookingId in metadata for webhook processing
  • Success URL → /success
  • Cancel URL → /cancel

Stripe Webhook

POST /api/v1/stripe/webhook
Headers: stripe-signature: whsec_...

The webhook verifies the Stripe signature using STRIPE_WHSEC_KEY, then:

  1. Extracts bookingId from session metadata
  2. Updates booking status to CONFIRMED
  3. Creates payment record with status SUCCESS
  4. Increments bookingsCount on the activity
  5. Syncs the activity to Recombee recommendations

All database operations happen inside a Prisma transaction for atomicity.

Payment Model

FieldDescription
bookingIdLinks to the booking
amountTotal charged
currencyUSD or NPR
statusPENDING / SUCCESS / FAILED / REFUNDED
providerSTRIPE (primary) or PAYPAL (available but not implemented)
stripePaymentIntentIdStripe reference ID

Stripe Configuration

Environment VariableDescription
STRIPE_SECRET_KEYStripe secret key (sk_test_... or sk_live_...)
STRIPE_PUB_KEYStripe publishable key (pk_test_... or pk_live_...)
STRIPE_WHSEC_KEYStripe webhook signing secret (whsec_...)

Testing

  1. Use Stripe test mode keys (sk_test_..., pk_test_...)
  2. Use whsec_... from Stripe CLI or Dashboard webhook settings
  3. Test card: 4242 4242 4242 4242 with any future expiry and any CVC
  4. For local webhook testing: stripe listen --forward-to localhost:3000/api/v1/stripe/webhook

Cancel Flow

PATCH /api/v1/bookings/cancel/:id
Response: { booking: { status: "CANCELLED" } }

Cancels a booking. Note: refund logic is not implemented in the API — cancellations require manual processing through the Stripe dashboard.

Supplier Booking Management

Suppliers can view bookings for their activities through the supplier dashboard (frontend) which calls:

GET /api/v1/bookings/supplier/:supplierId

This returns all bookings for activities owned by the given supplier.

Built with VitePress