Stripe Integration
Connect your organization's own Stripe account so clients can pay invoices online. Payments go directly to your Stripe account, and Ascent records each payment, refund, and dispute against the matching invoice automatically.
Overview
The Stripe integration lets you:
- Accept online invoice payments through Stripe's hosted Checkout page (card and US bank account / ACH)
- Send clients a public "pay this invoice" link that opens Stripe Checkout without requiring a login
- Optionally pass processing fees to the client as a convenience fee
- Automatically record successful payments and update invoice status
- Reconcile refunds and chargebacks (disputes) back onto the invoice via webhooks
- Optionally record Stripe processing fees as expenses in your financial accounts
This connects your organization's Stripe account for billing your MSP clients. It is completely separate from the platform billing for your Ascent subscription. Payments collected here are deposited into your own Stripe account.
Prerequisites
- Access to the Integrations admin area (the nav item requires the
integrations.managepermission and lives under the Admin section, which is available to Owner and Admin roles) - A Stripe account with a Secret Key and Publishable Key (from the Stripe Dashboard)
- Invoices to collect against (see Invoices)
Navigate to the integration
Go to Admin → Integrations, then click Stripe. The page is reachable at /admin/integrations → Stripe.
The top of the page shows a Connection Status card:
| Status | Meaning |
|---|---|
| Connected | Stripe is configured and active |
| Configured (Inactive) | Credentials are saved but the integration is disabled |
| Not Connected | No Stripe integration exists yet |
When configured, badges indicate whether you are running in Test Mode and whether Webhooks are enabled. The last connection error (if any) is shown beneath the status.
Setup
Step 1: Get your Stripe API keys
- Sign in to the Stripe Dashboard.
- Copy your Secret Key (
sk_live_...orsk_test_...). - Copy your Publishable Key (
pk_live_...orpk_test_...).
Keep your Secret Key confidential. Ascent stores it encrypted; never share or post it anywhere.
Step 2: Enter your keys in Ascent
In the API Credentials card:
- Paste your Secret Key.
- Paste your Publishable Key (used for the client-side payment form).
- Click Test Credentials to verify the secret key is valid before saving.
Step 3: Configure payment settings
In the Payment Settings card:
| Setting | Description |
|---|---|
| Processing Fee % | The percentage portion of your Stripe processing fee (defaults to 2.9) |
| Flat Fee | The flat per-transaction portion (defaults to 0.30) |
| Pass Fees to Client | When on, Ascent grosses up the charge and adds a separate Payment Processing Fee line item so the client covers the processing cost |
| Test Mode | Use your Stripe test keys for development |
| Enable Webhooks | Receive payment, refund, and dispute confirmations from Stripe (recommended) |
The standard Stripe fee shown for reference is 2.9% + $0.30 per transaction.
Step 4: Connect
Click Connect Stripe (or Save Settings if the integration already exists). On success the Connection Status card updates to Connected.
To remove the integration later, click Disconnect Stripe. After disconnecting, clients can no longer pay invoices online.
Webhooks
Webhooks let Stripe notify Ascent about payments, refunds, and disputes in real time. Enable Enable Webhooks and save, then a Webhook Configuration card appears with your details.
Each organization has its own webhook endpoint:
https://<your-instance>/api/stripe/webhook/<your-org-id>
The exact URL (including your org ID) is shown in the Webhook Configuration card.
To configure it:
- In the Stripe Dashboard, go to Developers → Webhooks → Add endpoint.
- Enter the per-organization webhook URL shown in Ascent.
- Select the events you want Stripe to send (see below).
- Copy the endpoint's Signing secret.
Ascent verifies each incoming webhook against your endpoint's signing secret before processing it. The Webhook Configuration card notes that the signing secret must be stored in your integration credentials for verification to succeed; the integration page does not currently expose a dedicated input for the signing secret.
Incoming webhooks are signature-verified, deduplicated (idempotent), and rate-limited per organization. If processing a valid event fails, Ascent schedules an automatic retry.
Events Ascent handles
| Event | What Ascent does |
|---|---|
checkout.session.completed | Records the payment when a Checkout session is paid |
checkout.session.async_payment_succeeded | Records the payment for delayed methods (e.g. bank transfers) that settle later |
checkout.session.async_payment_failed | Logs a failed-payment entry on the invoice history |
payment_intent.succeeded | Records the payment and updates invoice status |
payment_intent.payment_failed | Logs the failure (with Stripe's error message) on the invoice history |
charge.refunded | Records the refund as a negative payment and recomputes the invoice's paid amount and status |
charge.dispute.created | Flags the invoice with a dispute entry and notifies admins |
charge.dispute.closed | Records the dispute outcome on the invoice and notifies admins |
The Webhook Configuration card in the app lists payment_intent.succeeded and payment_intent.payment_failed as the minimum events. To capture Checkout payments, refunds, and disputes as well, subscribe to the full list above.
How clients pay
Online payments use Stripe's hosted Checkout page. Ascent creates a Checkout session for the invoice and redirects the payer to Stripe to enter their details, so card and bank data never touch Ascent's servers.
Public payment link
Each invoice has a public payment URL keyed to that invoice. When a client opens the link, Ascent verifies the invoice is eligible for payment and redirects them straight to Stripe Checkout — no login required.
An invoice can be paid online only when its status is one of: SENT, VIEWED, OVERDUE, PARTIAL, or PUBLISHED, and it still has a remaining balance. Invoices that are PAID, VOID, or CANCELLED cannot be paid.
What happens after payment
- The client completes payment on Stripe Checkout.
- Stripe notifies Ascent (via webhook) and/or Ascent retrieves the payment status after the redirect.
- Ascent records a Payment against the invoice, with the method detected as Credit Card or ACH based on the Stripe payment method.
- The invoice status updates to PAID (balance cleared) or PARTIAL (balance remaining), and a
payment_receivedentry is added to the invoice history.
Recorded payments appear under Billing → Payments. See Payments for more on tracking them.
Refunds, disputes, and fees
These are handled automatically when webhooks are enabled — there is no separate refund or dispute UI inside the Stripe integration page.
- Refunds: Issue refunds in the Stripe Dashboard. When the
charge.refundedwebhook arrives, Ascent records a negative payment, lowers the invoice's paid amount, and recalculates the status (back to PARTIAL or SENT as appropriate). Repeated webhooks for the same charge are deduplicated. Admins receive a refund notification. - Disputes (chargebacks): When a customer disputes a charge, Ascent adds a dispute entry to the invoice history and notifies admins so they can respond in Stripe. When the dispute closes, the outcome is recorded on the invoice.
- Processing fees: When the integration has an expense financial account configured (
expenseAccountId), Ascent records the Stripe processing fee for each successful charge as an expense in that account (best-effort; a failure here never blocks the payment). Note that the integration page itself does not expose a control for choosing this account.
Saved payment methods
Ascent exposes API endpoints to list and remove a client's saved payment methods stored in Stripe — both cards (brand, last 4, expiry) and US bank accounts (bank name, last 4). There is no dedicated screen for managing saved payment methods in the integration page itself; these are capabilities of the underlying API. The hosted Checkout flow does not save the payer's method by default.
Test mode
Before going live, enable Test Mode and use your Stripe test keys (pk_test_..., sk_test_...) with Stripe's test card numbers. Verify the full flow — payment, refund, and webhook delivery — then switch to your live keys and turn Test Mode off.
Security
- Card and bank details are entered on Stripe's hosted Checkout page and never pass through Ascent's servers.
- Your Stripe credentials are stored encrypted per organization.
- Webhook events are verified against your endpoint's signing secret before being processed.
Troubleshooting
- Credentials rejected: Use the Test Credentials button — it validates the secret key against Stripe before you save.
- Payments not recording: Confirm webhooks are enabled, the per-org webhook URL is correct in Stripe, and the endpoint's signing secret is stored in your integration credentials (the Webhook Configuration card explains this requirement). The Connection Status card surfaces the most recent error.
- Refunds or disputes not reflected: Make sure your Stripe webhook subscription includes
charge.refundedand thecharge.dispute.*events, not just the payment-intent events.
Tips
- Subscribe to the full event list so Checkout payments, refunds, and disputes all reconcile automatically.
- Leave Pass Fees to Client off unless your local rules and client agreements allow charging a convenience fee — when on, it adds a visible Payment Processing Fee line to the amount charged.