Skip to content

Stripe

Stripe lets Opentra (a) see when invoices are paid and (b) raise and send Stripe invoices for orgs you bill through Stripe.

Opentra needs three things from Stripe:

Credential Starts with Used for
Secret / restricted API key sk_… or rk_… Talking to Stripe (customers, invoices)
Webhook signing secret whsec_… Verifying that payment events really came from Stripe
Publishable key (optional) pk_… Not required — future client-side use

You paste these into Settings → Integrations → Stripe.

There are two paths, and understanding them is what stops payments double-counting.

Path A — client pays through Xero’s own Stripe gateway. The invoice is raised in Xero, the client clicks Pay Now and pays by card, and Xero marks its own invoice paid. Opentra’s Stripe webhook deliberately ignores these events (they carry no Opentra invoice metadata); instead the hourly Xero status sync notices the Xero invoice is paid and flips the Opentra invoice to Paid. This path needs the Xero integration connected and the worker running — the Stripe webhook is not involved.

Path B — Opentra raises the Stripe invoice. When a billing run is finalised for an org set to Payment method → Stripe, Opentra creates, finalises and sends a Stripe invoice tagged with its own metadata. When the client pays, Stripe fires invoice.payment_succeeded with that metadata → the webhook marks the Opentra invoice Paid / via Stripe and (if a clearing account is set) posts the payment back into Xero.

Does an org’s “Payment method” setting decide whether payments are recorded?

Section titled “Does an org’s “Payment method” setting decide whether payments are recorded?”

No. Each org has a Payment method setting (default Xero) that controls only whether Opentra also raises its own Stripe invoice at finalise. It does not gate payment detection — that’s driven by how the client actually pays:

Scenario Recorded as Paid? By what
Invoiced in Xero → client uses the Xero Pay Now (Stripe gateway) ✅ Yes Hourly Xero sync — for every org
Org set to Stripe → Opentra raises the Stripe invoice → client pays it ✅ Yes Stripe webhook (+ optional Xero write-back)
Client pays a standalone Stripe link never tied to the invoice ❌ No Reconcile manually

The hourly Xero sync is a universal safety net. You only need to set an org to Stripe if you want Opentra, rather than Xero, to generate and send the invoice.

A restricted key is recommended (least privilege); a standard secret key is quicker for a Test-mode trial.

Restricted key (recommended):

  1. In the Stripe Dashboard, confirm Test mode is on for your first pass.

  2. Go to Developers → API keys → Restricted keys → Create restricted key.

  3. Name it e.g. Opentra PSA, and set these permissions (everything else None):

    Resource Permission
    Customers Write
    Invoices Write
    Invoice Items Write
    Balance Read
    Charges Read
    PaymentIntents Read
  4. Create key, then Reveal and copy the value (rk_test_…) — Stripe shows it only once.

Standard key (quickest): under Developers → API keys → Standard keys, reveal and copy the Secret key (sk_test_…). Either key type works in Opentra’s “Secret key” field.

  1. In Opentra, open Settings → Integrations → Stripe and copy the webhook endpoint URL it displays (e.g. https://psa.yourshop.io/api/webhooks/stripe).
  2. In Stripe, go to Developers → Webhooks → Add endpoint.
  3. Paste the URL, describe it Opentra PSA, and select exactly these four events:
    • invoice.payment_succeeded
    • invoice.paid
    • payment_intent.succeeded
    • checkout.session.completed
  4. Save, then Reveal the endpoint’s Signing secret and copy it (whsec_…).

In Settings → Integrations → Stripe (Admin or Manager), fill in the Secret key, Webhook signing secret, optional Publishable key, and optional Xero clearing account code, then Connect Stripe. Opentra validates the key against Stripe before turning the badge green.

Only relevant if an org is billed via Stripe and you want the payment to appear in Xero. When set, Opentra posts the Stripe payment against this Xero account (e.g. a “Stripe Clearing” account) so your books stay complete. The code is the Xero account code (e.g. 090) from Accounting → Chart of accounts. Payments can only post to a Xero invoice that is Authorised (not Draft). Leave it blank to mark invoices paid in Opentra without writing to Xero.

  • Dashboard test: Developers → Webhooks → your endpoint → Send test webhook, choose invoice.payment_succeeded. An HTTP 200 confirms the secret and URL — Opentra logs “ignored: no metadata” for a bare test event, which is expected.
  • End-to-end: set a test org’s Payment method to Stripe, finalise a billing run for it, then pay the resulting Stripe invoice with test card 4242 4242 4242 4242. The Opentra invoice should flip to Paid / via Stripe within moments.

Repeat Parts 1–3 in Live mode: create a live restricted key (rk_live_…) with the same permissions, a live webhook (same URL, same four events) with its own live signing secret, and paste the live values in.

Symptom Likely cause
“Stripe rejected the key” when connecting Wrong key, or a restricted key missing Balance: Read.
Webhook attempts show 400 Signing secret doesn’t match the endpoint (test vs live mix-up), or pasted with whitespace.
Webhook shows 200 but invoice never marks paid The paid invoice wasn’t one Opentra raised. Payments via Xero’s own Stripe gateway are handled by the hourly Xero sync instead.
Paid in Stripe but not in Xero No Xero clearing account code set, or the Xero invoice isn’t Authorised.