Skip to main content

Platform billing (Stripe)

Ledgerline's own subscription / invoice surface — the rail by which Michael charges tenants for using Ledgerline. Separate from the end-customer payments that tenants take through their own stores; this is the platform charging the platform's customers.

The integration uses Stripe as the rail of record. Stripe handles cards, ACH, subscriptions, invoices, dunning, the billing portal, and PCI scope.

Pricing rails

  • Cards. 2.9% + 30¢ per successful charge.
  • ACH (US bank account). 0.8% capped at $5 per transaction.

Cards work for the long tail of small tenants and trial conversions. ACH is the path to paying down the per-transaction card take when monthly invoices get above ~$1,000.


For Michael (operator)

One-time setup

  1. Create a Stripe account (use the Ledgerline business email).
  2. In Developers → API keys, copy the Restricted key with the minimum scopes:
    • Customers: write
    • PaymentMethods: write
    • Invoices: write
    • Invoice Items: write
    • Subscriptions: write
    • Billing Portal Sessions: write
    • Webhooks: read
  3. Set STRIPE_SECRET_KEY=<sk_...> in the Render dashboard for ledgerline-api. The adapter binds itself on next deploy.
  4. In Developers → Webhooks, add a destination at https://ledgerline-api.onrender.com/api/stripe/webhook and subscribe to:
    • invoice.paid
    • invoice.payment_failed
    • customer.subscription.deleted
    • customer.subscription.updated
  5. Copy the webhook signing secret (whsec_...) and set STRIPE_WEBHOOK_SECRET in Render.
  6. In Products → catalog, create:
    • platform-monthly-flat price → set STRIPE_PRICE_ID_MONTHLY_FLAT
    • platform-annual-prepay price → set STRIPE_PRICE_ID_ANNUAL_PREPAY

Day-to-day

  • Onboarding a new tenant. When a tenant signs up, the platform-account service calls createCustomer and then createSubscription against the appropriate price id. The tenant is sent the hosted Billing Portal link for adding their card / ACH.
  • Looking at a tenant's invoice history. Use the Stripe dashboard search (filter by tenant id, which is stamped in the customer's metadata).
  • Refunding a charge. Issue refunds in the Stripe dashboard. The webhook will eventually emit charge.refunded — that event is currently ignored by the platform; reconciliation is manual until we wire it.
  • A tenant disputes a charge. Same dashboard. Dispute timeline is Stripe-managed; respond with evidence within 7 calendar days.

Status of a tenant's billing

StatusMeaning
activeSubscription is current.
trialingInside the trial window — no charge yet.
past_dueLast invoice failed. Payment method needs updating; tenant has reduced functionality after the dunning grace period.
cancelledSubscription cancelled, either by Michael or by Stripe after retries exhausted.
unpaidStripe gave up retrying — terminal failure.

Status transitions are driven by Stripe webhook events. A failure in our side of the loop (DB outage, etc) returns 5xx and Stripe retries for up to three days.


For tenants (operator-facing language)

Where to update your payment method

Use the link Michael sent you. It opens a hosted Stripe page where you can:

  • Update card or bank account
  • View past invoices and download PDFs
  • Cancel your subscription

That page is provided directly by Stripe — Ledgerline never sees your card number.

What if my card declines?

  • Stripe automatically retries the charge over the next several days using its Smart Retries policy.
  • You'll receive emails from Stripe with a link to update the card.
  • After the retry window expires, your subscription is marked unpaid and access to the dashboard's billable features is reduced. Reach out to support@ledgerline.com to recover.

ACH timing

ACH debits take 3-5 business days to settle vs. cards which settle within minutes. We mark the invoice paid only after Stripe confirms the ACH transfer, so plan accordingly.