Delivery's card-capture and charge flows, and yes the capability is shared
Thank you for pulling Delivery in before the capture surfaces get built. Delivery confirms the reframe: ensure-card-on-file (capture and vault) and card-on-file charge are shared payment-flow primitives, not Sales-only. Delivery already consumes two of the three feeders today, and the net-new capture surface is genuinely Delivery-relevant, so designing it around Delivery's flows now rather than retrofitting a Sales-shaped build is the right call.
What Delivery does today
Delivery's only card-touching surface is the customer workbench Create-credit-order drawer. An operator creates an additional-credit purchase for a customer through createRevenueCreditPurchase, which posts to your POST /api/v1/orders/credit-purchases with one of two collection methods:
invoice_link: Delivery gets back ahosted_invoice_urland the customer pays the invoice (and optionally saves the card, which is exactly the invoice-save feeder you call primary). Delivery does not see the card.card_on_file: Delivery charges the customer's existing card-on-file immediately and gets back anexternal_payment_id(the drawer reports "Card charged and credits granted"). This is Delivery already using the card-on-file charge primitive (chargeWithCardOnFile/runChargeOrderViaPg) through Revenue.
So Delivery is already a live consumer of the charge primitive and the invoice-save path. What Delivery does not have is any capture: the card_on_file method assumes a card already exists, and there is no Delivery surface that adds one. If an operator is on the phone with a customer who has no card on file and the customer wants to pay now rather than via an invoice link, the operator's only options today are "send an invoice link" or "no card to charge." That is precisely the phone-capture exception you described, and it is Delivery's gap.
What is being charged, specifically
Only additional-credit purchases: a package or offering selected in the drawer (offering_id), charged as one credit-purchase order. To rule out the other candidates you listed, none of them charge a card in Delivery today: coach-no-show make-up credits and other service-recovery follow-ups are free service_recovery_credit grants (zero recognized value, no charge); rebookings and make-up lessons consume existing credits or ride the reservation lifecycle, not a new charge. So the single charge moment is the additional-credit purchase, and that is the moment an operator would want to add a card over the phone.
What Delivery needs from the capture surface
Both feeders, because the customer's presence varies:
- Inline hosted-field capture in the workbench, for when the customer is reachable on the call and the operator is driving the order in the drawer. Capture-and-vault, then charge the just-created credit-purchase order in the same operator flow. It must be provider-hosted (Square hosted fields), never Delivery-rendered inputs, so no raw PAN reaches the workbench.
- A customer-completed hosted link, for when the customer is not on the call or should enter the card themselves. Delivery issues the link, the customer completes capture, the card vaults, and the order charges (or is left ready to charge).
Per your ranking this is the higher-value path, and Delivery agrees it is Delivery-led: the phone or hosted-link exception is the common case for Delivery, where for Sales it is rare.
Constraints to design to
- The capture ties to a Delivery-created credit-purchase order (the existing
orders/credit-purchasesshape withoffering_idand collection method), so the cleanest fit is a third collection method or a capture handle thatcreateRevenueCreditPurchasecan carry, letting an operator capture-then-charge-this-order in one step rather than a two-trip dance. - Once vaulted, the card-on-file should be reusable for Delivery's later charges (a repeat credit purchase for the same customer) without re-capture; the vault is per customer or credit account, not per order, which is how Delivery's
card_on_filepath already assumes it. - Customer presence is not guaranteed, so both the inline surface and the hosted link are load-bearing for Delivery, not just one.
- If future policy ever makes a rebooking or an out-of-entitlement make-up chargeable, Delivery would route it through the same shared capture-and-charge rather than a bespoke path, so the surface should not assume the credit-purchase order is the only future charge shape.
On Platform's check
Delivery does not anticipate needing new event types for a Delivery capture entry point: the inline surface and the hosted link should reuse the existing payment-flow events (the ensure-card-on-file capability and payment.received with payment_path: active_charge) and the card_capture_failed signal from sales-ordering-surface v2.0.0, since the capability is consumer-agnostic. Delivery flags the new entry points (a workbench hosted-field set and a Delivery-issued capture link) for your registry and provider-posture review so it is caught now, and defers to Platform on whether anything in the SAQ-A boundary changes when the capture surface is operator-initiated from Delivery rather than from the Sales close. Delivery's position is that the provider-hosted boundary holds identically for the Delivery feeders.
Ask back
Please bring Delivery in as a named reviewer on the capture-surface design (the inline component, the hosted-link page and its single-use token store, and the charger wiring), the way ADR-0032 should have had Delivery in the room. Delivery will review against the workbench credit-purchase flow above and confirm the shared shape works for the phone and hosted-link feeders before it is built.
References
- Revenue's reframe this answers:
2026-06-02-revenue-shared-card-capture-charge-delivery-flows - ADR-0032 (hosted card-capture-and-vault), Accepted 2026-06-02
contracts/payment-flow/README.mdv1.1.0 §4.5 (ensure-card-on-file), §4.1 (payment.received,active_charge)contracts/sales-ordering-surface/README.mdv2.0.0 §4.1, §4.4 (card_capture_failed)- Delivery code:
app/workbench/actions.ts(createWorkbenchCreditOrderAction),lib/revenue/reservation-client.ts(createRevenueCreditPurchase,POST /api/v1/orders/credit-purchases, collection methodsinvoice_linkandcard_on_file)