Carrier Payouts and the Wallet
When a Levy Cover claim is approved and paid, the funds come from the carrier, not from Levy. The carrier chooses the destination (card, bank, PayPal, or Levy wallet) based on the rider's selection at claim time. This page describes what happens for each destination - especially the Levy wallet case, which has strict accounting rules.
Payout destinations
The carrier supports four payout destinations:
| Destination | Mechanism | Touches Levy books? |
|---|---|---|
| Card | Refund to original payment method via carrier's processor | No |
| Bank | ACH or wire to rider's bank | No |
| PayPal | PayPal email transfer | No |
| Levy wallet | Wallet credit posted in Levy | Yes |
For the first three, Levy receives a payout.completed webhook for visibility only - the funds go from the carrier to the rider directly, and Levy's ledger is unaffected. The status on insurance_claims moves to paid and the operator sees it in the claims queue.
The Levy wallet case is different. Funds flow from the carrier to Levy, and Levy posts a wallet credit to the rider. This page focuses on that case.
The wallet payout rule
`insurance_claim_payout` requires a real insurance_claims row
A wallet credit with reference_type = 'insurance_claim_payout' is only valid if it references an existing row in insurance_claims via reference_id. The creditWalletForRefund helper enforces this with a database lookup. There is no path for creating an insurance_claim_payout credit without a real claim record.
Why the strict requirement:
- Audit. Every wallet credit must trace back to a documented event. Premium refunds trace to a
ride_refundsrow; claim payouts trace to aninsurance_claimsrow. Both paths require their reference to exist. - Anti-abuse. Without the guard, a misconfigured cron, a typo in a script, or a malicious operator could create wallet credits typed as insurance payouts but not corresponding to any actual claim. The DB-level enforcement prevents this.
- Settlement reconciliation. Levy reconciles wallet payouts against the carrier's settlement file monthly. Mismatches indicate misposted credits and are surfaced as ops tasks.
What insurance_claim_payout is for
wallet_transactions.reference_type = 'insurance_claim_payout' is specifically for carrier-issued claim payouts. It is not for:
- Premium refunds. Those reference
ride_refundsrows. See Premium Refunds via the Ride. - Goodwill credits. Those have their own reference type and are explicitly not insurance.
- Operator-initiated wallet credits to make a rider whole for an off-platform issue.
If you find yourself reaching for insurance_claim_payout but you do not have an approved insurance_claims row with status IN ('approved', 'paid'), the credit is the wrong type. Stop and choose the correct path.
The flow for a wallet-destined payout
- The carrier (Cover Genius) approves the claim and the rider elected Levy wallet as the destination.
- The carrier issues a
payout.completedwebhook with:claim_idmatching the carrier's claim ID stored oninsurance_claims.carrier_claim_idpayout_amountandpayout_currencypayout_destination = "levy_wallet"
- The webhook handler in
src/lib/insurance/webhook-handlers.ts:- Verifies the signature.
- Looks up
insurance_claimsbycarrier_claim_id. If no row exists, the webhook is rejected (this is the guard). - Inserts an
insurance_payoutsrow referencing the claim. - Calls
creditWalletForRefundwithreference_type = 'insurance_claim_payout'andreference_id = insurance_claims.id.
- The wallet helper verifies the
insurance_claimsrow exists with the expected status and posts the credit. - The rider receives a push notification: "Your Levy Cover payout of $X has been added to your wallet."
What rides.net_deposited does NOT do
Claim payouts do not touch rides.net_deposited on the underlying ride. The ride was already accounted correctly:
- Premium was charged.
- Carrier net was set aside.
- Levy and operator commissions were recorded.
- The ride is closed.
The claim payout is a downstream insurance event. It happens because a valid policy did its job. The original ride accounting was correct and stays correct.
This is the opposite of a premium refund, which does touch net_deposited because the underlying ride needs correction (the premium should not have been kept).
Side-by-side comparison
| Scenario | Reference type | Touches net_deposited? | Requires row in... |
|---|---|---|---|
| Premium refund (ride was overcharged) | ride_refund | Yes (recalc via RPC) | ride_refunds |
| Carrier payout to wallet (valid claim) | insurance_claim_payout | No | insurance_claims |
The two paths look superficially similar - both end in a wallet credit referencing some other row - but the meaning and the accounting downstream are completely different.
Failed wallet posts
If the wallet credit fails (e.g. the rider account is closed):
- The
insurance_payoutsrow is created withwallet_transaction_id = NULL. - The
payout.completedevent is logged ininsurance_webhook_logwithprocessed_at IS NULL. - Ops investigates - typically the rider must reach out to recover, or Levy reports the wallet path as unavailable so the carrier reroutes to card/bank.
The carrier handles the reroute. Levy does not initiate a refund on a failed payout - those funds are the carrier's to redirect, not Levy's to refund.
Levy's settlement with the carrier
Wallet payouts post immediately for the rider. Behind the scenes, Levy settles with the carrier monthly via the carrier's reconciliation system (XPay for Cover Genius). The cash flow is:
- Carrier owes Levy: the sum of wallet-destined payouts in the month.
- Levy owes carrier: the sum of carrier-net premiums collected on bound policies in the month.
- These net out, and Levy or the carrier pays the difference.
This settlement is handled at the platform level; individual subaccounts see only the per-claim payout events, not the netting.
Next
Read Premium Refunds via the Ride for the opposite-direction case. Together, those two pages cover every cash movement related to Levy Cover.
Need help?
Questions on carrier payouts and the wallet, contact support@levyelectric.com.