Skip to main content
Fire spark has not launched publicly yet. API and platform changes will be documented here after the first release.
Breaking (pre-GA): Merchant-scoped resources no longer expose organization_id. Scope children by merchant_id (and env when applicable). Storefront realtime topics are sf:{merchant}:{env}. Merchants and organization endpoints still include organization_id.
Reopen a cancelled order
  • Storefront POST /orders/:id/reopen also accepts an order already VOIDED, REVERSED, or legacy CANCELLED that was never fulfilled, once every real tender is CANCELLED, FAILED, or fully REFUNDED. A kiosk can return to checkout after a failed injection whose card was reversed on the device. Nothing is voided again and no webhook is sent. A PAID tender (reversal in flight) is still 400 ORDER_PAYMENT_CAPTURED; an IDLE or PENDING one is 422 ORDER_NOT_REOPENABLE. REFUNDED orders stay rejected: a refund only happens after delivery.
SDK 0.6.0 — virtualized category scroll-spy and checkout release
  • @fire-spark/rn-ui useActiveCategory accepts an index mode for virtualized lists (FlashList, FlatList, LegendList). Pass rowSectionIds, headerIndex, and listRef. onScroll reads getFirstVisibleIndex. FlatList can use onViewableItemsChanged. selectCategory calls scrollToIndex. The offset mode (categoryIds, offset, scrollRef, registerCategory) is unchanged. @fire-spark/react-ui stays on offset mode.
  • @fire-spark/storefront adds buildMenuRows, menuRowKey, menuRowType, and spanMenuRow. They turn flattened sections into header, product, and empty rows for those lists.
  • See Displaying menus.
  • @fire-spark/realtime adds watchCheckoutRelease. It subscribes to order.changed and settles when checkout_state is released or failed, so place order can stay loading until the fulfillment releases checkout. Call arm once place order is in flight to start the timeout (60 s by default, timeoutMs), consider to feed a payload you already have, and stop on unmount. Pass current to settle at once on a known state. Exports the CheckoutReleaseWatch and CheckoutReleaseResult types.
SDK 0.5.0 — one redeem model (breaking)
  • Breaking: every redeem (order or line) requires payment_id, an active REDEMPTION payment of the merchant, and amount > 0. A redeem without them is rejected (REDEEM_PAYMENT_REQUIRED); an unknown, inactive or non-REDEMPTION payment returns REDEEM_PAYMENT_METHOD_NOT_CONFIGURED.
  • Line money, taxes and totals stay full. redeem[].amount is shown as the discount and its REDEMPTION tender pays it; the customer’s method pays the rest. before_taxes (default true) caps the redeem at the pre-tax value, so taxes stay for another method. Example: 10 + 15% tax with a redeem of 10 gives REDEMPTION 10 + CASH 1.50; with before_taxes: false the redeem can cover 11.50 and REDEMPTION pays everything.
  • Tender amount is { currency, total }. allocation.amounts[] is { line_uid, units?, total, children } with gross line money. Old breakdown keys (subtotal, discount_total, tax_total, fees, tip, delivery, redemptions_applied) are dropped on read.
  • Order validation returns REDEEM_AMOUNT_MISMATCH for a redeem above its cap.
  • redemption_steps follow the same model: one step per redeem, in application order (root-line redeems, then order redeems), with payment_id, before_taxes and discount_amount = the capped amount. The steps of a payment_id add up to its REDEMPTION tender; a step never lowers line money or totals, and after.value is what the customer’s method still pays. The server recomputes and stores them, and validate/place still reject client steps that differ: REDEMPTION_STEPS_MISMATCH (other redeems or order) and REDEMPTION_MISMATCH (other money). New redemptionSteps().
  • Renamed: groupPaymentRedeems → groupRedeems, orderPaymentRedeems → orderRedeems, paymentRedeemsCoverTotal → redeemsCoverTotal, clampPaymentRedeems → cappedRedeems. isPaymentRedeem is removed. New orderPayableTotal gives what real tenders must pay.
  • Stored redeems without payment_id are skipped on read; they are never written.
  • Breaking: a rejected cart sync (POST/PATCH) is no longer swallowed. The draft still rolls back to the last synced order, and the next placeOrder / setTenders throws OrderSyncRejectedError (a StorefrontHttpError with the API status, code and details) instead of placing the stale order.
  • Breaking: place has no cash default. Without intent_id or payment.type, POST /orders/{id}/place returns 422 PAYMENT_REQUIRED, unless the redeems cover the whole total (then only REDEMPTION tenders). order.placeOrder() throws OrderPaymentRequiredError (code: PAYMENT_REQUIRED) before calling the API. Send the picked method, with its merchant payment.id.
  • Release with pnpm sdk:release minor.
SDK 0.4.0 — redemption amounts (breaking)
  • Breaking: redeems and REDEMPTION tender details carry money only. points and program are gone from order.applyRedeem, orders.redeem and details. details.points_value and rewards[].points_value are now amount.
  • Details stored with the old keys are still read: points_value becomes amount and points / program are dropped. They are never written.
  • order_payment_operations.points and the Tinybird order_payments_metrics.points column are removed.
  • Release with pnpm sdk:release minor.
SDK 0.3.2 — reopen
  • Storefront POST /orders/:id/reopen voids unpaid tenders, cancels the source order as VOIDED, and returns a new OPEN order. The link is metadata.reopen (as_order_id on the source, from_order_id on the new order). A captured real tender returns 400 ORDER_PAYMENT_CAPTURED. Integrations receive order.voided.
  • SDK order.reopen(). On a kiosk, Cancel during the checkout-release wait calls it.
  • All 15 @fire-spark/* packages are 0.3.2.
SDK 0.3.1 — redemption tenders
  • Redeems that share a payment_id are one REDEMPTION tender. details.rewards[] lists them. points and points_value are the sums. amount and points on the redeem are totals for the entry.
  • services.payments.list hides REDEMPTION unless { includeRedemptions: true }.
SDK 0.3.0 — tenders
  • An order’s payments are payment_intents[].tenders[]: method, amount, status, collect_at, and allocation. is_mixed is true when there are two or more real tenders.
  • Storefront: PUT and DELETE /orders/:id/payment-intent, POST /orders/:id/payments, and tender void, replace, and refund. Place locks a saved draft with intent_id, or builds one real tender from payment.
  • SDK: setTenders, payIntent, retryTender, replaceTender, voidTender, refundTender. order.pay calls payIntent.
Payments SDK
  • New payments packages: @fire-spark/payments (shared contract) and @fire-spark/payments-cash. Register them with order.setPaymentAdapters and charge with order.pay. See Use payments in the SDK.
  • Split payments: an order is paid when the sum of its PAID intents covers the total.
  • Provider webhooks land on /api/webhooks/payments/{provider}.
  • Kiosk devices accept settings_overrides.payment_settings, with secret fields masked on read.
  • New monitoring trigger: Payment terminal failures.
  • New supported payment methods page.