Client billing portal
What a client sees and does in Billing — view the agreement, approve it, set up AutoPay, download invoices and raise a change request.
Client billing portal
Everything a client needs for billing lives in one place in their own panel: /admin/billing. This page covers what they see, what they can do, and the honest rules behind approvals and change requests — so support conversations stay short.
Who this is for
Business owners and admins (the client side), and Super Admins who need to know what the client sees.
- Difficulty: Easy
- Time: 5 min
- Prerequisites: Signed in as the workspace owner or an admin. Managers and members never see billing at all.
The four client pages
| Page | URL | What it shows |
|---|---|---|
| Billing & Subscription | /admin/billing |
The workspace's billing overview |
| Your Billing | /admin/billing/agreement |
The commercial agreement: status, price, included services, approval and AutoPay setup |
| Invoices | /admin/billing/invoices |
Their invoices, with plain statuses and signed download links |
| Payment History | /admin/billing/payments |
Every recorded payment |
Step 1 — Approve the agreement
- Open Your Billing (
/admin/billing/agreement). - Read the plain-language summary: agreement name, price, billing start/end, included services and any notes.
- Click Approve.
The approval is recorded with the time, IP address and user agent — that is the audit trail. After approval the status becomes AutoPay setup pending and the next step is to authorize AutoPay.
Step 2 — Set up AutoPay
Click the AutoPay button to go to the payment provider (Razorpay or Cashfree) and authorize the mandate.
Coming back from the provider is not the finish line When the client returns to the CRM, the platform does not trust the redirect. It re-checks with the provider directly and only shows Active once the provider confirms the authorization. Until then the status stays "AutoPay setup pending" with the message: "We are still confirming your payment setup." If a mandate already exists, the platform re-verifies it instead of asking for a second authorization.
Step 3 — Read the status in plain words
| Status shown | What it means to the client |
|---|---|
| Draft | Not sent yet (internal) |
| Awaiting your approval | Sent — waiting for their approval |
| AutoPay setup pending | Approved — waiting for provider confirmation |
| Active | All good; renewals are automatic |
| Payment failed | A payment did not go through |
| Grace period | Extra time before anything changes |
| Past due | A stronger reminder; still working |
| Restricted | Only CRM, leads, follow-ups and reports remain |
| Suspended | Access is blocked — contact your account manager |
| Cancelled / Expired | The service has ended |
The mechanics behind these words are in Payment failures & restrictions.
Step 4 — Download invoices
The invoices page shows each invoice as Paid / Due / Partially paid / Overdue — internal DRAFT and VOID invoices never appear. Downloads use signed links, so a link only works from the portal session it was generated in.
Step 5 — Raise a change request
If the client wants a different price or different services, they use the change-request flow on the agreement page. Two honest rules:
- The change request never modifies the live agreement. It is a proposal.
- If the change affects the amount, the new amount must be authorized at the provider — a new provider authorization is required; it cannot be applied silently.
The request reaches the Super Admin team, who review and apply it (or reject it with a reason). If the client needs a subscription cancelled instead, the panel also has a Cancel subscription page (/admin/billing/cancel) for the plan subscription.
Expected result
The client can see exactly what they are paying for, approve it, get the mandate live, and find every invoice and payment without contacting support.
Common mistakes
- Expecting instant activation after the provider redirect. Provider confirmation takes a moment; the page explains this honestly.
- A manager trying to open Billing. The section is gated to owner or admin — nothing appears for managers/members.
- Treating a change request as done when sent. It is a proposal until the team applies it, and amount changes additionally need provider authorization.
- Sharing an invoice download link over chat. Signed links are session-bound; ask the client to download from their portal instead.
- Confusing "Subscription" (plan) with "Agreement" (commercial contract). Per-client pricing lives in the agreement.
Troubleshooting
| Symptom | What to check |
|---|---|
| "We are still confirming your payment setup." | The provider has not confirmed yet; if it persists for hours, support should check the reconciliation alerts |
| AutoPay button missing | Agreement not yet approved, or the provider is not configured |
| Download link "expired" | Signed link lifetime is short; re-open from the Invoices page |
| Recent payment not visible | Provider webhook delay; check again shortly, or support can verify the transaction |
| Client says they paid by bank transfer | Payments outside AutoPay must be recorded manually by the team — contact your account manager |
Technical details
- Pages:
App\Filament\Pages\CommercialBilling\BillingHome("Your Billing", slugbilling/agreement),CommercialInvoices(slugbilling/invoices),CommercialPayments(slugbilling/payments); legacyApp\Filament\Pages\Billing\BillingPortalat/admin/billingandCancelSubscriptionat/admin/billing/cancel. - Access gate: Super Admin, or the tenant owner, or a user with the Spatie
adminrole. - Approval stores IP and user agent; statuses mapped in
BillingHome::STATUS_LABELS. - AutoPay:
BillingHome::activateAutoPay→ provider, thenBillingService::verifyAuthorization()on return (PROVIDER_RETURN_KEYStriggers the re-check). - Change requests:
BillingChangeService— proposals only; applied changes are versioned and audited. - Provider integration:
app/Billing/Commercial/*; webhooks at/api/webhooks/razorpay|cashfree.
Related guides
Was this page helpful?
Thanks — noted. ✦