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 (processing → done) 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.