Skip to main content

Invoicing

[billing] [admin]

Stripe Connect based billing: licensio = platform, providers = connected accounts. Flat platform fee: 10 % in the beta (resolveProvisionPercent, overridable per provider, see Access & terms). Stripe Tax automatic.

Who it is for​

Admins. The "Invoicing" tab collects all data that Stripe needs for correct invoices, VAT and payment processing.

What you set​

  • e.g. "Plant Technology GmbH"
  • Set in Stripe as business_profile.name
  • Appears on every invoice as the sender

Address​

  • Street, zip, city, country
  • Stripe attempts to set this as company.address (Express accounts often only accept it via onboarding)

Tax​

  • VAT ID: added to the Stripe tax_ids
  • Tax number: informational, printed on invoices
  • Stripe Tax must be enabled separately in the Stripe dashboard (Tax tab → Automatic Tax ON)

Contact​

  • Email (for Stripe mails)
  • Phone number

Your own logo that appears on Stripe invoices. Upload via:

  1. licensio storage (for the preview in the admin)
  2. Stripe Files API with purpose: 'business_icon'
  3. accounts.update on the connected account with settings.branding.logo

Recommended: square PNG, ≥256x256, < 200 KB.

Step by step​

1. Enable Stripe Connect​

Settings → Stripe → Create account → Stripe onboarding (Express account). Provides your bank data, person verification etc.

2. Fill the invoicing tab​

Fill in all fields + upload a logo. Save automatically triggers the Stripe sync (best-effort).

3. Enable Stripe Tax in the dashboard​

  • dashboard.stripe.com → Tax → Settings
  • Automatic Tax to ON
  • Tax registrations → add Germany
  • The company address must be complete

4. Test the first package​

Create packages → on save a Stripe product + price is created. Visible in the Stripe dashboard under Products of the connected account.

5. First payment​

Two paths, depending on who starts it:

  • Admin "Activate" (Freischalten): activation always creates a Stripe send_invoice invoice (14-day due date, auto_advance, payment methods derived by preflight from the connected account's Connect capabilities — card / sepa_debit; none active → error). There is no checkout on the admin path. The customer stays pending_payment and only becomes active via the invoice.paid webhook.
  • End-customer self-service (/join): the customer goes through the Stripe checkout (subscription for monthly packages or a single charge for one-off ones).

Webhook events confirm the payment in licensio.

Operational note (required per provider Stripe account): disable Stripe's own invoice/subscription emails in the Stripe dashboard (Settings → Billing → Invoices / Subscriptions and emails), otherwise the customer receives a duplicate mail. The licensio mail with the hosted-invoice link is the only customer mail.

Stripe Tax: logic​

SenderRecipientVAT IDResult
DEDEany19 % VAT
DEEUwith VAT IDReverse charge 0 %
DEEUwithout VAT IDLocal rate of the recipient country
DEnon-EUany0 %

Stripe applies this automatically when automatic_tax: { enabled: true } and tax_behavior: 'exclusive' (net prices).

Webhook events (incoming)​

There are two Stripe webhooks with different purposes: confusing them leads to signature errors and broken plan updates.

Provider portal webhook: /api/stripe/webhook (<slug>.licensio.io)​

Processes payments from your end customers (Stripe Connect):

  • checkout.session.completed: first payment successful
  • setup_intent.succeeded: payment method saved (Flow B)
  • invoice.paid: recurring payment
  • invoice.payment_failed: payment failed (notification + dunning)
  • charge.refunded: refund
  • customer.subscription.updated / .deleted: subscription lifecycle
  • account.updated: connected account status

Secret in ENV: STRIPE_WEBHOOK_SECRET (portal Vercel project).

licensio platform webhook: /api/stripe/licensio-webhook (admin.licensio.io)​

Processes your own paid plan subscription at licensio (an upgrade done later inside the admin — registration itself is always the free access):

  • checkout.session.completed: new paid plan subscription
  • customer.subscription.updated: plan change, renewals
  • customer.subscription.deleted: cancellation → provider falls back to the free access (plan = free)
  • invoice.payment_failed: payment error on your plan invoice

Secret in ENV: LICENSIO_STRIPE_WEBHOOK_SECRET (admin Vercel project). Writes directly into tenants.plan, plan_started_at, licensio_stripe_customer_id, licensio_subscription_id.

Invoices in the portal​

Customers see their Stripe invoices directly in the portal account tab "License & contract" → invoices tile with PDF download (via the Stripe Invoices API).

Frequently asked questions​

How high is the platform fee? A flat 10 % in the beta (application_fee_percent on every Stripe subscription, resolved by resolveProvisionPercent; overridable per provider via settings.provision_percent). The rest goes to you. Visible in the Stripe dashboard as an application fee. Details: Access & terms.

Who sees my Stripe data? Only you. licensio platform admins have read access for support cases, but no modification rights.

What if the Stripe webhook fails? The webhook endpoint validates signatures with STRIPE_WEBHOOK_SECRET. On failure Stripe retries automatically (~several hours). Error logs are visible in the Vercel logs.

Can I also send invoices without Stripe? Currently everything runs via Stripe. Manual invoicing (PDF generation outside Stripe) is not implemented.

Reverse charge for EU customers: how? Stripe Tax detects EU VAT IDs automatically (validated via VIES). If the customer enters a VAT ID at checkout, reverse charge is applied. tax_id_collection is enabled in our checkouts.