Mutation
Fields
checkoutCheckoutResult!Price a basket, mint the order, and — when money is owed — the PaymentIntent to pay for it. The single entry point that replaces registerForActivity, purchaseProduct, bookActivityTime, signUpTeam and signUpIndividual: one mutation, any mix of items, one order.
Two phases. This one writes a pending purchase and its lines, holding no capacity and spending no credits, and returns a CheckoutSession for the client to confirm with Stripe Elements. completePurchase (or the webhook backing it up) then fulfills it. A free or fully credit-funded basket skips Stripe entirely and comes back already completed, with a null checkoutSession — the same free-versus-paid contract the mutations it replaces had.
Works signed-out when the business allows guest checkout: pass buyer with the buyer's email and a bot-challenge token.
Arguments (1)
inputCheckoutInput!completePurchaseCompletePurchaseResult!Fulfill a minted purchase once its payment has been confirmed: books the sessions, mints the entitlements, spends the credits, and records how the order was funded, all in one transaction.
Idempotent, and safe to race — the Stripe webhook calls the same routine, so a buyer who closes the tab mid-confirm still gets their booking exactly once.
Authorized by possession of the unguessable purchase id, so a guest can finish their own checkout. A signed-in caller must additionally own the purchase, so a leaked id cannot be completed by a third party.
cancelBookingCancelBookingResult!Cancel a booking and, under the activity's cancellation policy, return the money and the credits it consumed. Booking.cancellationPreview says what this will do before it is called.
Arguments (1)
bookingID!joinBookingWaitlistJoinWaitlistResult!Join the queue for a full session. Writes a waitlisted booking with no order behind it — nothing is charged until a place is offered and accepted.
For a card-paid activity, pass a confirmed SetupIntent so the vaulted card can be charged off-session if the place is offered automatically.
Arguments (2)
sessionEntityRef!inputJoinWaitlistInputacceptBookingOfferCheckoutResult!Accept an offered place. Re-enters checkout for the amount owed, so the result carries a CheckoutSession exactly as checkout does; the existing waitlisted booking is confirmed rather than a second one inserted.
Arguments (1)
bookingID!createAccountRequestAuthCodeResult!Request an email containing a 6-digit code to confirm a new account. Always returns success regardless of whether the email is already in use (anti-enumeration). If an account already exists for the email, a sign-in code is sent instead.
When businessHandle is set, the issued code is pinned to that business and the resulting token is scoped to it (does not set a cross-account cookie). Used by the business-pinned embed sign-in flow.
When name is set and the email resolves to a brand-new account at redemption time, that name is applied to the inserted user row. Ignored for emails that already have an account.
signInRequestAuthCodeResult!Request a sign-in email containing a 6-digit code. Always returns success regardless of whether the email matches an existing account (anti-enumeration).
When businessHandle is set, the issued code is pinned to that business and the resulting token is scoped to it (does not set a cross-account cookie). Used by the business-pinned embed sign-in flow.
redeemAuthCodeSignInResult!Redeem a 6-digit auth code and sign the user in. Returns the created or signed-in user, the JWT token, and the redirect URL stored on the code. Sets the auth cookie on success — except for codes that were issued with a business pin, which return a business-scoped token without touching the cookie session.
confirmSocialSignUpSignInResult!Create the account a social sign-in stopped short of creating, and sign in as it. token is the pending sign-up handed to a popup opener; omit it and the pending cookie is used instead (the popup-blocked flow, which has no opener to hand anything to). name is the viewer's chosen display name, falling back to whatever the provider shared.
Resolution is re-run from scratch, so an account that appeared in the meantime — another tab, an email sign-up — is linked rather than forked. Sets the auth cookie, or returns a business-scoped token for an embed.
cancelSocialSignUpCancelSocialSignUpResult!Discard a pending social sign-up without creating anything. Clears the pending cookie so a later page load doesn't ask again.
registerForActivityRegisterForActivityResult!Register for an individual activity session. Use productPurchase to pay with an existing pass/membership, or omit it for direct purchase. Pass guest to register on behalf of someone else; the caller is recorded as the booker and pays. The activity's participant policy must allow guest registrations.
Pass buyer when the caller is not signed in to perform guest checkout. Requires the business's guestCheckoutEnabled setting.
Arguments (19)
activitySessionEntityRef!productPurchaseEntityRefspotEntityRefThe reserved spot being bought, for a session selling against a spot map. The caller must already hold it — pass the same holderKey given to holdSpots, or the registration is refused as a lost race.
spotHolderKeyStringThe checkout key the spot holds were taken under. Required with spot.
seatSectionEntityRefThe general-admission section being bought into, for a spot map whose section sells as a capacity pool rather than assigned spots. Mutually exclusive with spot.
formData[RegistrationDataInput!]Register someone else, with the caller as the booker. Requires a signed-in caller. Omit guest.email to book without notifying the attendee — see GuestRegistrationInput.
familyMemberEntityRefRegister one of the signed-in viewer's managed children (a FamilyMember with role child). The viewer must be a manager or guardian sharing a family with the member; the booking is recorded with the viewer as the booker and the child as the participant. Mutually exclusive with guest.
buyerBuyerInputdiscountCodeStringOptional discount code typed by the customer. Validated server-side against the activity's business; an invalid or unmet code returns a per-field error rather than registering at full price.
giftCardCodeStringOptional gift-card code to apply against the registration price. The card's remaining balance covers up to the post-discount line; any remainder is charged via Stripe.
paymentMethodStringStripe PaymentMethod ID captured via SetupIntent for paid card waitlists. Required when the registration falls onto the waitlist for a card-paid activity (no productPurchase); used to charge the customer off-session if their spot is later promoted.
savePaymentMethodBooleanWhen true for a signed-in card checkout, attach the newly-entered card to the buyer's Stripe Customer for future purchases. Ignored for guest checkout and saved-card waitlist reservations.
taxCalculationIdStringStripe Tax calculation ID returned by a recent quoteTax query. When provided, the server reuses that calculation. Ignored when the seller has tax disabled.
tipAmountIntOptional gratuity in cents. On a paid registration it rides the same charge, added after tax; on a pass/membership-covered one it mints a tip-only checkout instead of confirming immediately — the registration (and the pass debit) then commits only once the tip payment succeeds, so an abandoned checkout registers nothing. A tip is always excluded from both the tax base and the platform-fee base, and ignored for a waitlist join or a registration with no session. Tipping is per-activity: an activity that does not accept tips rejects a non-zero tipAmount outright. Classes, sessions, leagues and tournaments default to not accepting tips; bookings default to accepting them.
emailMarketingConsentBooleanEmail-marketing opt-in captured on the registration form. true records an affirmative consent for this participant against the activity's business; only honored when the business has consent collection enabled. Sessions never sends marketing email itself — consent lets the business email the participant through its own provider.
emailMarketingConsentDisclosureVersionIDVersion of the consent disclosure the buyer was shown. Frozen with the consent record so the proof reflects exactly what they agreed to.
attributionAttributionInputMarketing attribution captured client-side (UTM parameters, referrer host, landing path). First-touch is stamped onto a newly created participant; last-touch onto the registration. The server classifies the trustworthy origin — a client-claimed marketplace origin is never trusted.
idempotencyKeyStringOpaque client-generated idempotency token, stable for one checkout attempt (e.g. a single crypto.randomUUID() minted when the payment step mounts, NOT regenerated per click). When provided, it is used as the Stripe idempotencyKey on the saved-card off-session charge so a double-submit / client retry deduplicates to a single live charge instead of charging twice. Omit it to keep the legacy behaviour.
bookActivityTimeAppointmentBookingResult!Books an open time range on a structure: booking activity. Validates [startAt, endAt) is a contiguous run of the activity's open increments whose increment count is within [minIncrements, maxIncrements], then creates the booking — an activityId-tied appointment session + registration. Free bookings confirm immediately; activities set to request mode create a pending request the business approves or declines. Paid bookings charge bookingPricePerIncrement × increments and create the booking only once payment succeeds (via completeCheckout). buyer supplies guest details when the caller is not signed in.
productPurchase redeems one of the caller's passes/memberships (as surfaced by Activity.bookingPaymentResolution) against the booking: a pass spends the activity's creditCost (default 1) per booked increment, so a covering purchase settles the whole booking for creditCost × increments, confirming immediately via the free path — no charge, no checkout (unless a tip is added; see tipAmount). It's all-or-nothing — the purchase must belong to the buyer, be active, cover the activity, and (for a finite session count) have enough sessions for the whole booking; otherwise it's rejected and the caller pays by card.
formData carries answers to the activity's registration blocks — intake questionnaires and consent/waiver signatures collected before the appointment — persisted as block metadata + an agreement PDF on the resulting registration, exactly like registerForActivity.
tipAmount adds an optional gratuity (cents). On a paid booking it rides the same charge, added after tax; on a pass/membership-covered booking it mints a tip-only checkout instead of confirming immediately — the booking (and the pass debit) then commits only once the tip payment succeeds, so an abandoned checkout books nothing. A tip is always excluded from both the tax base and the platform-fee base, and ignored for free bookings. Tipping is per-activity — a booking activity accepts tips by default, but one whose operator turned tipping off rejects a non-zero tipAmount outright.
emailMarketingConsent records the participant's optional opt-in to the business's marketing email, exactly like registerForActivity — honoured only when the booked activity carries an emailMarketing registration block and the business has consent collection enabled.
Arguments (10)
activityEntityRef!startAtDateTime!endAtDateTimeRequired (and meaningful) only for a duration-priced activity, where the client chooses the range. For a services activity the end is derived server-side from the selected services and this value is ignored.
services[EntityRef!]The selected menu services for a services-priced activity: exactly one primary service plus any add-ons. Must be omitted for duration activities.
buyerBuyerInputformData[RegistrationDataInput!]productPurchaseEntityReftipAmountIntemailMarketingConsentBooleanattributionAttributionInputMarketing attribution captured client-side. See registerForActivity.
cancelActivityRegistrationCancelActivityRegistrationResult!Cancel an existing activity registration.
Arguments (1)
idID!completeCheckoutCompleteCheckoutResult!Complete a checkout after Stripe confirmation, then fulfill the underlying entity (pass purchase or registration). Idempotent — safe to call multiple times.
Two flows converge here:
- Guest (pay-only): the client already confirmed a PaymentIntent on the
business's connected account; this verifies it succeeded.
- Signed-in (save-and-pay): the client confirmed a SetupIntent that
vaulted the card on the viewer's platform wallet and passes the resulting paymentMethod; the server clones it onto the connected account and runs the (off-session) direct charge here, so the card joins the unified wallet and the business is merchant of record.
purchaseProductPurchaseProductResult!Purchase a product (pass, membership, gift card, or physical product). Returns a checkout session if payment is required, or the purchase directly for free products.
Pass buyer when the caller is not signed in to perform guest checkout. Requires the business's guestCheckoutEnabled setting. Passes and memberships always require a signed-in user.
Arguments (16)
productEntityRef!buyerBuyerInputdiscountCodeStringOptional discount code typed by the customer. Validated server-side against the product's business; an invalid or unmet code returns a per-field error rather than purchasing at full price.
giftCardCodeStringOptional gift-card code to apply against the product price. The card's remaining balance covers up to the post-discount line; any remainder is charged via Stripe.
paymentMethodIDExisting saved Stripe PaymentMethod to charge. Currently used for membership subscriptions so a signed-in buyer can subscribe without re-entering card details.
savePaymentMethodBooleanWhen true for a signed-in one-shot card checkout, attach the newly-entered card to the buyer's Stripe Customer for future purchases. Ignored for guest checkout and memberships.
taxCalculationIdStringStripe Tax calculation ID returned by a recent quoteTax query. When provided, the server reuses that calculation rather than computing a fresh one — guaranteeing the buyer is charged the amount they saw. Ignored when the seller has tax disabled.
forRegistrationBooleanSet when this purchase exists only to fund a registration that's being booked in the same flow (the buyer picked "buy a pass" as the payment method on a session). For a single-use pass the spot consumes the only session immediately, so the standalone purchase-confirmation email is suppressed — the registration confirmation already covers it. Multi-use passes still send the purchase email since sessions remain.
recurringConsentAcceptedBooleanSeparate affirmative consent for recurring membership charges. Required when purchasing a membership; ignored for one-time products.
emailMarketingConsentBooleanEmail-marketing opt-in captured at checkout. true records an affirmative consent for this buyer against the product's business; only honored when the business has consent collection enabled. Sessions never sends marketing email itself — consent lets the business email the participant through its own provider.
emailMarketingConsentDisclosureVersionIDVersion of the consent disclosure the buyer was shown. Frozen with the consent record so the proof reflects exactly what they agreed to.
attributionAttributionInputMarketing attribution captured client-side. First-touch is stamped onto a newly created participant; last-touch onto the purchase. See registerForActivity.
idempotencyKeyStringOpaque client-generated idempotency token, stable for one checkout attempt (e.g. a single crypto.randomUUID() minted when the payment step mounts, NOT regenerated per click). When provided, it is used as the Stripe idempotencyKey on the saved-card off-session charge so a double-submit / client retry deduplicates to a single live charge instead of charging twice. Omit it to keep the legacy behaviour.
fundingSourceCheckoutFundingSourceWhich funding source the buyer picked, when the product offers a choice (see Membership.bankDebit — memberships only). Defaults to CARD. BANK is a request: the server re-checks the operator toggle, the rail, the connected account's capability, and the minimum amount, and silently bills the subscription to a card instead when any of them says no. Unrelated to paymentMethod, which is a saved Stripe PaymentMethod id.
bankDebitMandateIDA bank-debit mandate the buyer has already authorized, as the Stripe SetupIntent id returned by createBankDebitMandateSetup. Required for a rail that can't collect its mandate from a deferred-intent Payment Element (Canadian pre-authorized debit — see BankDebitCheckoutOption.mandateSetupRequired); ignored unless fundingSource is BANK.
With one, the subscription is created already billing the mandated bank account: its first invoice is confirmed server-side rather than by the client, and the returned checkout is only there so the caller can completeCheckout it. The server re-reads the SetupIntent from Stripe and requires it to have succeeded against this buyer's own customer, so an id from anywhere else is refused rather than trusted.
createBankDebitMandateSetupCreateBankDebitMandateSetupResult!Mint a SetupIntent on the business's connected account so the buyer can authorize a bank-debit mandate before the subscription they're paying for exists.
For rails that cannot collect a mandate from a deferred-intent Payment Element — Canadian pre-authorized debit, which Stripe refuses there outright — this is what the bank form mounts against. Confirm it with confirmSetup, then hand the SetupIntent id to purchaseProduct as bankDebitMandate.
Re-runs the gates behind Membership.bankDebit server-side, plus the connected account's capability, and returns an error rather than a mandate when any of them says no — unlike the charge-time gate, there is nothing to silently fall back to here: the buyer asked for a bank form.
Arguments (1)
productEntityRef!addFavoriteAddFavoriteResult!Add a business, staff member (instructor), or activity to the authenticated user's favorites. Idempotent — adding an existing favorite is a no-op.
Arguments (1)
favoriteFavoriteTargetInput!removeFavoriteRemoveFavoriteResult!Remove a business, staff member, or activity from the authenticated user's favorites. Idempotent — removing a favorite that isn't set is a no-op.
Arguments (1)
favoriteFavoriteTargetInput!