Promo Codes and Deposits
This guide covers two of the most-used customizations for Levy Bookings: discount codes you can hand out to customers, and refundable security deposits that protect you from damage and theft.
Promo codes
Promo codes are subaccount-scoped discounts that customers enter on the payment step. The system validates the code, applies the discount, and increments the redemption count atomically.
Create a promo code
- Open Dashboard > Bookings > Promo Codes.
- Click New promo code.
- Fill in:
| Field | Example | Notes |
|---|---|---|
| Code | SUMMER25 | What customers type. Case-insensitive. Letters, numbers, dashes only. |
| Discount type | Percent / Fixed / Free add-on | See below |
| Discount value | 25 (for 25%) | For percent: 1-100. For fixed: cents off. For free add-on: the add-on ID. |
| Starts at | 2026-06-01 | First date the code is valid |
| Ends at | 2026-09-01 | Last date the code is valid |
| Max redemptions | 100 | Total uses across all customers. Blank for unlimited. |
| Applies to | All models / Specific models / Specific add-ons | Scope the discount |
| Min quantity | 1 | Useful for group discounts ("4+ riders") |
| Active | yes | Toggle to disable without deleting |
- Save.
Discount types
- Percent. Knocks a percentage off the subtotal. "SUMMER25 = 25% off."
- Fixed. Knocks a dollar amount off the subtotal. "BIKE10 = $10 off."
- Free add-on. Includes a specific add-on at no charge. "FREEHELMET = one free helmet add-on."
Fixed discounts are capped at the subtotal so they cannot result in a negative total. Percent discounts apply before tax.
How customers redeem
On the payment step of the hosted page or widget, customers see a Have a promo code? link. They tap it, type the code, and the price updates live.
If the code is invalid, expired, or already at its redemption cap, the field shows "This code is not valid" with no further detail (to discourage code-guessing attacks).
Abuse prevention
Every promo-code endpoint is rate-limited by IP and per-email. If a single visitor tries 5 invalid codes in a row, additional attempts get throttled for a cooldown period.
If you suspect a code has leaked publicly, set its Active to off — already-confirmed bookings keep their discount, but new ones can no longer use the code.
Reporting
In Dashboard > Bookings > Promo Codes > {code}, you see:
- Total redemptions / max redemptions.
- Total discount given (in dollars).
- Total booking revenue tied to this code (gross GMV before the discount).
- List of every booking that used the code.
Useful for ROI on a promo campaign — what was the gross GMV vs. the discount spend.
Refundable security deposits
Refundable deposits protect you from damage, theft, or excessive wear. They are held on the customer's card (not charged) via a Stripe pre-authorization, then released automatically on a clean return.
When to use a deposit
Use a deposit when:
- Your fleet has expensive vehicles ($1,500+ retail).
- You have a history of damage or "casual theft" that you absorbed.
- Customers might leave the city / country with your vehicle.
- You want to gate the rental experience for unverified first-time customers.
Skip deposits when:
- Your fleet is low-cost (sub-$500) and you write off occasional damage as a cost of business.
- Your customers are predominantly returning locals you trust.
- The deposit friction would kill conversion (resort spa, premium positioning).
Configure deposit defaults
- Open Dashboard > Bookings > Widgets > {your widget}.
- Scroll to Deposit defaults.
- Set:
- Deposit amount (cents) — e.g. 20000 for a $200 deposit.
- Capture window — how long Stripe holds the pre-auth before auto-releasing (default 7 days, configurable up to 7 days max per Stripe).
- Auto-release on clean return — yes by default. The deposit releases as soon as the return is marked clean on the iPad POS or in the dashboard.
You can also override the deposit amount per vehicle model in Dashboard > Vehicles > Models > {model} > Deposit.
How the customer experiences it
On the payment step, the customer sees:
- "Rental total: $80.00"
- "Refundable deposit: $200.00 (released within 7 days)"
- "Total authorized: $280.00"
When the customer pays with a card (or Apple Pay or Google Pay), Stripe captures the $80 rental and pre-authorizes (but does not capture) the $200 deposit. The customer's card statement shows a pending charge for $280 that drops back to $80 once the deposit releases.
Releasing the deposit
On the iPad POS during the return flow, staff tap Release deposit for a clean return. The Stripe pre-auth is cancelled, the customer's card sees the $200 hold disappear, and the reservation records deposit_status = released.
You can also release from the web dashboard on any reservation detail page.
Capturing the deposit (for damage)
If there is damage:
- Open the reservation.
- Tap Capture deposit > Full or Capture deposit > Partial.
- Enter the dollar amount (must be ≤ the original deposit).
- Enter a reason and attach photos.
- Confirm.
Stripe captures the specified amount. The remaining deposit (if any) is released back to the customer. The captured amount is recorded as a separate deposit_capture transaction on the reservation so it does not get mixed with rental revenue in your tax remittance.
Automatic release timing
If you do not manually release a deposit, Stripe automatically releases it after the capture window expires (default 7 days from the original authorization). To keep the customer's hold short, mark the return promptly — every Levy operator who runs deposits should be doing same-day release on clean returns.
Refunds with deposits
If the customer cancels before pickup:
- The rental is refunded per your refund policy.
- The deposit pre-auth is released immediately (regardless of policy — pre-auths are not subject to refund policy).
If the customer returns the vehicle but disputes a damage capture, follow the standard Stripe dispute flow. The captured deposit is treated like any other Stripe charge.
Combining promo codes and deposits
Promo codes apply to the rental subtotal only — they do not affect the deposit amount. If a customer books an $80 rental with a $200 deposit and applies a SUMMER25 code, they pay $60 (75% of $80) and are still pre-authorized for the $200 deposit.
Always refund through the reservation
This is the single most important rule in Levy Bookings, copied straight from the platform-wide refund policy: always refund through the reservation, never directly to the wallet.
If a customer overpaid, was overcharged, or is owed money:
- Use the Refund button on the reservation detail page (web dashboard or iPad POS).
- For a fare adjustment (the booking was correct but you want to lower the price), use the Adjust fare flow.
Never:
- Directly credit
customers.wallet_balancein the database. - Insert into
wallet_transactionsmanually. - Call internal wallet credit helpers outside of the refund flow.
The ride / reservation is the source of truth for net revenue, tax remittance, and partner payouts. Crediting the wallet without adjusting the reservation corrupts all three. The wallet is just where the money lands — it is never the starting point for a refund.