Skip to main content

ADR-0011 — Stripe Terminal as the card processor

  • Status: Accepted
  • Date: 2026-04-28
  • Decision-makers: Tom Anderson

Context

Bike shops need in-person card processing — tap, chip, swipe — at the counter. Three options for the BC Canadian market:

  • Stripe Terminal (BBPOS WisePOS E, S700) — modern API, good docs, supports Canadian merchants, decent Interchange-plus pricing
  • Helcim — Canadian-owned, very good Canadian rates, modern API, smaller terminal ecosystem (Smart Terminals)
  • Square Terminal — strong UX, US-first; Canadian rates less competitive than Helcim/Stripe; less integration flexibility
  • Moneris — Canadian incumbent, legacy enterprise tooling, no modern API worth integrating

The processor decision affects:

  • Per-shop cost of accepting cards (interchange + processor fee)
  • Hardware purchase / lease arrangement
  • Integration complexity (how the Worker talks to the reader)
  • Refund / dispute / payout flows
  • Onboarding friction for new shops

Each shop owns its own merchant account, so Helm doesn't carry their card volume on its balance sheet. Money flows shop → processor → shop's bank, never through Kvick.

Decision

Use Stripe Terminal as the default card processor. Specifically:

  • BBPOS WisePOS E hardware (Canada-supported; ~$300 CAD per unit)
  • Per-shop Stripe account (Connect Standard for the platform relationship, but each shop's account is their own)
  • Per-shop Stripe Reader Locations and Reader registrations
  • Helm calls Stripe via fetch() to /v1/payment_intents and /v1/terminal/readers/{id}/process_payment_intent
  • Idempotency keys on every charge
  • Webhook signature verification on every webhook
  • Stripe holds the PCI scope; Helm sees no raw card data

Helcim remains an option for shops with high Canadian volume where the Stripe rate is uncompetitive. The integration would be in a separate adapter (src/lib/helcim.js) and shop config would pick which to use. v0.1 ships Stripe only.

Consequences

Positive:

  • Best documentation and SDK ergonomics
  • Stripe's webhook + idempotency story is mature and well-trodden
  • Modern API matches the rest of our integration patterns (boring tech — Stripe is boring in the good sense)
  • Hardware is widely available
  • Stripe Connect Standard means each shop has their own dashboard, payouts, and disputes

Negative:

  • Stripe's Canadian rates are not the cheapest; Helcim beats them
  • Stripe Reader hardware lock-in (the API works only with their terminals)
  • Stripe's Canadian compliance forms are extensive at onboarding (mitigated by Connect Standard, where Stripe handles most of it)

Mitigations:

  • Document the Helcim option for shops that ask
  • The adapter pattern (src/lib/{processor}.js) keeps swap cost reasonable
  • Stripe's reader hardware is good; the lock-in is acceptable for the integration quality

Notes

For e-commerce (the shop's public site → Helm) we use Stripe Checkout, not Terminal. Same vendor, different product, same adapter file.

See also