docs

Payment processor

Card charges, invoicing, and refunds run through your own payment processor account. heliumOS provides the integration layer and never holds funds — money lands in your balance.

Like carrier and tax credentials, the payment connection is configured from the operator dashboard, not from the API. Operator API keys cannot read, rotate, or delete processor credentials. It is environment-scoped and resolved on every call, so sandbox and live each carry their own processor and their own credentials — one processor account per environment.

Sandbox vs live

  • Sandbox can use a built-in stub that charges, invoices, and refunds deterministically with no external calls, so you can build your billing integration before you have processor credentials. It can equally hold your processor's test credentials if you would rather exercise the real integration.
  • Live uses Stripe with your account's live secret key. On save, heliumOS runs a verify round-trip and surfaces any credential problem before the connection goes active.

Stripe connections also carry an inbound webhook signing secret so heliumOS can reconcile invoice, payment, and refund status back from Stripe. The endpoint URL and the event list to register are shown on the connection's detail page; the whsec_… secret Stripe issues for it is added afterward, on the same page. Until it is set, the connection can charge cards but will not reconcile.

Subscriber email verification

The connection carries one setting that is not a credential: "We verify a subscriber's email address before we create the subscriber." It is off by default and it changes one thing — whether a returning subscriber keeps the processor customer record they already have.

What it changes

The first time heliumOS needs a processor customer for a subscriber, it creates one. That is right for a genuinely new person and wrong for someone who cancelled and came back: they already have a customer record on your processor account, carrying their saved cards, their credit balance, and their payment history. Creating a second one splits that person across two records that look identical in the processor's dashboard.

With this setting on, heliumOS first looks the person up on this environment's processor account by exact email address, and gives them the record they already have.

What you are asserting, and why we ask

The email address arrives on POST /v1/subscribers under your API key. heliumOS has no way to check that the person on the other end of your signup owns it — only you do. So turning this on is an assertion about your signup flow, made per environment, alongside the credentials for the processor account it authorizes searching.

If the address is not verified, whoever holds your API key can attach a new subscriber to any unclaimed customer on your processor account by naming its email address, and reach the payment methods saved on it through POST /v1/subscribers/:subscriber_id/payment_sessions. That is why the default is off. Leave it off if you are not certain.

The records heliumOS will not take

Even with the setting on, an existing record is only adopted when all of these hold. Otherwise a new customer is created, exactly as before:

  • the record's own email address matches the subscriber's;
  • no other heliumOS subscriber in this environment already holds it, and it is not tagged as belonging to a different subscriber;
  • it carries no debit balance — money the person owes would otherwise be applied silently to their first heliumOS invoice, with no line explaining it. A credit balance is inherited;
  • it carries no live processor subscription — one on each record would bill the person twice, from two systems;
  • the lookup itself succeeded. Not being able to tell whether someone owes money is not treated as evidence that they don't.

Nothing here can fail the billing operation that triggered it: every refusal falls back to creating a new customer.

Turning it on

From the dashboard: Payment processor → your connection → Subscriber email verification. Owner and admin roles only, and it is its own confirmation step rather than something that rides along with a credential change.

The assertion names one processor account, so anything that could point the connection at a different account withdraws it and asks again: replacing the connection, and rotating its secret key (or its Connect account id). Adding the inbound webhook signing secret does not — it cannot move the account.