Prerequisites
- An existing checkout built with Stripe Payment Elements, using your own
PaymentIntentflow. - Stripe Dashboard access, with permission to create API keys.
- Gale Merchant Dashboard access.
Step 1: Create your custom payment method
A custom payment method type is what makes Gale appear in your Payment Element. Create one per Stripe account, in each mode.Open Custom payment methods

Settings → Payments → Custom payment methods

Custom payment methods → Create
Set the name and logo

Create custom payment method → Provide a custom name and icon

Display name, logo, and the terms checkbox
Copy the cpmt_ id
cpmt_. Copy it and keep it
somewhere handy — you need it in the steps that follow, and Stripe displays
it only once.
Custom payment method created — note the cpmt_ id
Step 2: Connect Stripe to Gale
Gale needs access to your Stripe account to import your catalogue and write payment records back. Do this once per Stripe account, per mode, on the Gale on Stripe page in your Gale Merchant Dashboard.Create a restricted Stripe API key
Paste your credentials into Gale
Import your products
product_id, so your catalogue
has to be here before a checkout can resolve eligibility.Turn on Keep products in sync and later edits in Stripe reach Gale on
their own. See Import
products.Confirm the connection is good
Step 3: Add Gale to your checkout
Two changes in your frontend, and one new endpoint on your backend. Your backend is what calls Gale, so it authenticates with your API key (glm_test_… / glm_live_…). Generate one in the Gale Merchant Dashboard under
Developer Tools → API Keys — see Getting your API
key. Keep it server-side;
it must never reach the browser.
Frontend — register the CPM
customPaymentMethods,
documented for the Payment Element
here.paymentMethodOrder: ['cpmt_...', 'card'] when
you create the Payment Element.Frontend — branch on submit
stripe.confirmPayment.
Gale adds a branch before the intent is created, and leaves the card path
untouched.Backend — create the Gale checkout
Step 4: Set your Gale webhook URL
Gale reports payment outcomes to your application over webhooks. Set your endpoint under Developer Tools → Webhooks in your Gale dashboard, then subscribe to the events you need:Test vs live
Everything on the Stripe side is mode-dependent — sandbox and live each need their owncpmt_ id. Your Gale key carries its environment in the prefix:
glm_test_… or glm_live_….
One-time vs subscription
There are twomode settings and they’re separate: the one in your <Elements> options is Stripe’s deferred-mode setting, and the one in the cart metadata is what Gale reads. Keep them consistent.
- One-time — omit
modein the cart metadata, or sendmode: 'payment'. A single charge. Stripe receives the payment record once the charge has settled, not at the moment of authorisation, so the record reflects money that actually moved. - Subscription — send
mode: 'subscription'. See below.
Subscriptions on this path
Gale owns the subscription and initiates every renewal. There is no Stripe subscription and no Stripe invoice — Stripe receives a payment record per cycle, for reporting only.Starting one
Sendmode: 'subscription' in the cart metadata and put a plan_id on each
line item. The amount and cadence come from the plan, never from the cart.
plan_idis required on every subscription line item — there is no fallback to “the product’s only plan”. A plan that is unknown, archived, or not attached to that product returns422 PLAN_NOT_FOUND.intervalandinterval_countare rejected in cart metadata. Cadence belongs to the plan.priceis optional, but if you send it, it must equalamount × quantityfrom the plan.
Renewals reach you over Gale webhooks only
Gale schedules and charges every renewal, so Gale’s webhooks are the only place a renewal is announced. Your existing Stripe Billing handlers will never see one — there is no Stripe subscription and noinvoice.paid.
Refunding a cycle
Refund the order the cycle produced, withPOST /v2/refunds and your API
key — there is no per-cycle refund call. Each cycle in
GET /v2/subscriptions/{id} carries the order_id it produced. Gale reports
the refund to Stripe against the payment record.
Subscriptions
/v2/subscriptions API
work — the same on every Gale integration.Failure modes
- Wrong or missing API key, or a key from the other environment →
401/422from/api/v2/checkout. - Line item missing
product_id→422. It’s required on every line item. Aproduct_idthat Gale doesn’t recognise as HSA/FSA-eligible is accepted — that item just charges on the non-eligible leg. success_url/failure_urlnot HTTPS → checkout creation is rejected. Use a tunnel or a local certificate in development.- Payment Records not enabled on your Stripe account → the charge still completes normally; the record just won’t appear in Stripe.
Test your integration
Use test credentials
glm_test_… Gale key and your test-mode cpmt_… id. Environment
is encoded in the key prefix — nothing else about the request changes.Confirm the option renders
cpmt_ id that does not belong to the publishable key mounting the Element.
Also check that Adaptive Pricing is not active. No Gale setting changes this.Confirm the branch skips stripe.confirmPayment
Create a checkout
POST /api/v2/checkout and answers
{ data: { checkout_url, checkout_id } }, and the shopper lands on the
Gale-hosted card page.Run a mixed cart
product_id Gale does not recognise as eligible. It
should still charge, on the non-eligible leg, rather than being rejected.Confirm the outcome server-side
reference_id you sent — this is the authoritative record — and that a
payment record appears in Stripe against your custom payment method,
shortly after the charge settles rather than at authorisation.Test cancel and decline
failure_url
and can pay another way, with the order left unfulfilled.Go-live checklist
- Live Gale key (
glm_live_…) on the live code path, and the livecpmt_id in the Element product_idpresent on every line itemsuccess_urlandfailure_urlare HTTPS- Stripe Payment Records enabled on your account, so charges appear for reporting
- Outcome verified server-side before fulfilment
- One real live transaction reconciled in both the Stripe and Gale dashboards
- Team knows refunds and disputes go through Gale, not the Stripe Dashboard
