Skip to main content

Mark booking payment as processing (Public API)

Summary

A new GraphQL mutation, markBookingPaymentProcessing, moves a booking from pending to processing after the partner's client has successfully confirmed the Stripe PaymentIntent. This mirrors the existing online-booking REST endpoint setBookingPaymentIsProcessing.

Payment completion (processingdone) still comes from Stripe webhooks and is not handled by this mutation.

Mutation

mutation MarkBookingPaymentProcessing($paymentIntentId: String!, $bookingId: ID) {
markBookingPaymentProcessing(
paymentIntentId: $paymentIntentId
bookingId: $bookingId
) {
success
error
deleted
data {
id
onlineBookingPaymentStatus
}
}
}

Arguments

ArgumentRequiredDescription
paymentIntentIdYesStripe PaymentIntent id returned when the payment intent was created for the booking; this is the stable correlation key for retries and webhook races
bookingIdNoOptional booking id guard; when provided, it must match the booking row that stores this payment intent

Response

FieldDescription
successtrue when payment status moved from pending to processing
dataUpdated booking when success is true
codeMachine-readable failure code when success is false (NOT_FOUND, ALREADY_PROCESSING, ALREADY_PAID, INVALID_STATE)
errorHuman-readable failure reason when success is false
deletedtrue when the matched booking has been soft-deleted (for example by an expiry job). Omitted when the booking is not deleted.

When to call

Call immediately after successful client-side PaymentIntent confirmation (confirmPayment, including redirect return flows), before relying on payment being marked done.

Typical partner flow:

  1. createBooking — create the appointment
  2. Create a payment intent for the booking (via your payment-intent mutation when available)
  3. Confirm payment in the browser with Stripe.js
  4. markBookingPaymentProcessing — tell Semble checkout is in progress
  5. Wait for Stripe webhooks to mark payment done and create the invoice

Failure behaviour

The mutation fails safely without modifying data when:

  • No booking in the authenticated practice stores the given payment intent id
  • Payment status is not pending
  • Optional bookingId does not match the booking for that payment intent

Failure outcomes are explicit:

  • NOT_FOUND + Pending booking not found when no matching booking is visible in scope
  • ALREADY_PROCESSING + Booking payment is already processing when retrying after a successful transition
  • ALREADY_PAID + Booking payment is already paid when webhook completion has already moved payment to done
  • INVALID_STATE + Booking payment is no longer pending for other non-pending states

When a booking was found but is not eligible, deleted is true if the booking has already been cleaned up.

If a booking was soft-deleted while payment was still pending (for example slot expiry during checkout), the mutation can still succeed and returns { success: true, deleted: true }. Partners should treat this like the online booking flow: payment may have gone through but the slot was already released.

Authorization

Access is scoped to the authenticated practice credential (same as other booking mutations). An online-booking token is not used.