Troubleshooting
A step-by-step checklist for the most common Levy Bookings issues. Start at the top — most problems are caught by the first three checks.
The booking page returns "This booking page is not yet open"
The widget is disabled. Open Dashboard > Bookings > Widgets > {your widget} and toggle Enabled = true. The change takes effect immediately, no deploy needed.
The booking page shows "No models available"
Your subaccount has no vehicle models with a published pricing tier. Levy Bookings needs at least one model with a pricing tier in order to show anything.
- Open Dashboard > Vehicles > Models — make sure at least one model exists.
- Open Dashboard > Pricing — make sure that model has a published pricing tier.
- Verify the widget's Default pricing tier points at a real tier (or any model has a tier override).
If you have multiple models but only some have pricing tiers, only the ones with tiers will appear in the picker — by design, so a model with no tier cannot be booked.
The embedded widget does not appear on my site
In order of likelihood:
- The
<script>tag is missingdata-slugor has a typo. Open the page source — make suredata-slugmatches your widget slug exactly. - The
data-targetelement does not exist. Fordata-mode="inline", the target element (default#levy-bookings) must be in the DOM when the script runs. If your site renders the target asynchronously, add the script after the target. - Content Security Policy blocks the iframe. Open your browser console — if you see
Refused to frame 'https://widget.levyelectric.com', your site has a strict CSP. Addframe-src widget.levyelectric.com(or*) to your CSP. - The script was pasted inside a text block, not a code block. Squarespace and Wix strip
<script>tags from text blocks — paste into a Code block or Embed block instead.
CORS errors when submitting a booking
If you see "Origin not allowed" or "Blocked by CORS policy" in the console when the customer clicks Pay:
- Open Dashboard > Bookings > Widgets > {your widget} > Allowed origins.
- Make sure the exact origin of the page hosting the widget is listed. Origins are matched exactly:
https://www.frankebikes.comdoes NOT matchhttps://frankebikes.com.https://frankebikes.comdoes NOT matchhttp://frankebikes.com.
- Add both
https://andhttps://www.variants if your site redirects between them. - If you preview on a staging URL, add that too (e.g.
https://staging.frankebikes.com).
GET requests (availability, quote) work from any origin. Only POST requests (booking creation, waiver submission) require an allowlisted origin.
Apple Pay button does not appear
Apple Pay shows up only when:
- The customer is using Safari on a device with Apple Pay set up.
- Their device has at least one card stored in Apple Wallet.
- The widget's Allowed payment methods > Apple Pay is on (it is by default).
- The page is loaded over HTTPS.
If all four are true but the button still does not appear, open Safari's Web Inspector → Console and look for Apple Pay errors. The most common culprit is the customer's wallet has zero cards. Test on a different device to confirm it is not a widget configuration issue.
"Card was declined" on a test card
The Stripe test card 4242 4242 4242 4242 only works on a Stripe test key. Your widget is using a live key (which is correct for production). To test:
- Use a real card and refund it immediately, or
- Set the subaccount to demo mode (a Levy admin can do this) — it switches the connected account to Stripe test keys for all of Levy Bookings.
Demo accounts always use test keys; production accounts always use live keys.
Waiver does not save / signature is blank
The signature pad uses an HTML5 canvas. Three known causes:
- The customer drew with a mouse on a touchscreen device. Switch input method — use a finger or stylus, not a mouse hovering near the screen.
- The browser has aggressive privacy settings. Brave with Shields at maximum, or Firefox with Resist Fingerprinting, can break canvas drawing. Suggest the customer try a different browser.
- The customer cleared the signature mid-draw. The Clear button wipes the canvas — they need to redraw.
If the signature draws fine but does not save, check the network tab for a 4xx response on /api/widget/{slug}/bookings/{id}/sign. The most common cause is the access token in the URL has expired (24-hour window) — the customer needs to start a fresh booking.
Stripe Terminal reader will not connect
For BBPOS WisePOS E:
- The reader must be on the same Wi-Fi network as the iPad.
- Power-cycle the reader (hold the power button for 5 seconds).
- In the POS, Settings > Card Reader > Forget reader, then re-discover.
For Tap to Pay on iPhone:
- Verify the iPhone is on iOS 16.4 or newer.
- Verify you are in the US, UK, or Canada — Tap to Pay is not yet available in all regions.
- Make sure the iPhone is signed in to iCloud — Tap to Pay requires it.
- Accept the Stripe Tap to Pay terms when prompted.
If a connection token error appears in the console, the Stripe connected account for this subaccount may not be enabled for Stripe Terminal. Open a support ticket and we can enable it.
POS pairing PIN expired
PINs are valid for 10 minutes. Generate a new one in Dashboard > Bookings > POS and try again. If you keep hitting the timeout, generate the PIN and have the iPad ready to enter it within seconds.
Confirmation email did not arrive
- Check spam / promotions tabs.
- Verify the customer entered the email correctly — most "missing email" cases are typos.
- In Dashboard > Reservations > {booking}, check the email log. If the log shows "delivered," the email was sent successfully — the customer's mail server is filtering it.
- If the log shows "bounced," the email address is invalid.
If you need to resend, open the booking and tap Resend confirmation.
SMS confirmation did not arrive
- Verify the customer entered the phone number correctly with country code.
- SMS uses your subaccount's Twilio integration. Check Dashboard > Settings > SMS — if Twilio is not configured, no SMS is sent (the email confirmation still goes).
- Some carriers (Verizon especially) filter SMS from short-codes if the customer has aggressive spam settings. Suggest they whitelist the short code.
Promo code is rejected as invalid
The promo-code endpoint returns "not valid" for any of these reasons (the UI does not distinguish between them, to prevent code-guessing):
- Code does not exist.
- Code is disabled (
Active = no). - Code is outside its
starts_at/ends_atwindow. - Code has hit
max_redemptions. - Code does not apply to the items in cart (e.g.
applies_to = [Model A], customer is booking Model B). - Code requires a minimum quantity the customer has not met.
Open the code in the dashboard to see which of these is the actual cause.
Inventory mismatch — "Sold out" but I have vehicles
The booking engine respects model_inventory_caps for the widget's pickup location. If the cap is below your actual vehicle count, the widget will sell to the cap.
- Open Dashboard > Car Sharing > Reservations > Inventory.
- Find the cap row for this model + location + time window.
- Raise the cap (or remove it).
Also check whether the cap is being eaten by overlapping reservations from other channels (mobile app, walk-in). The cap counts all reservations regardless of source.
Customer says they were charged but did not get a confirmation
Open Dashboard > Reservations and search by their email or phone. The most common cause is the customer started a booking, the payment succeeded, but they closed the browser before the confirmation page rendered.
The booking exists. Their card was charged. Tap Resend confirmation to send them the email + SMS again.
If the booking does not exist but Stripe shows a charge, that is a true edge case — open a support ticket with the Stripe charge ID. We have safeguards against this and we will refund + investigate.
Webhook events not firing
Levy Bookings emits webhooks for booking.created, booking.confirmed, booking.cancelled, booking.refunded. Configure endpoint URLs in Dashboard > Settings > Webhooks.
If events are not firing:
- Confirm your webhook URL responds with
2xxto a test ping (use the Test endpoint button). - Check the Webhook log for delivery attempts and HTTP response codes.
- If your endpoint returns
5xx, we retry with exponential backoff up to 24 hours, then give up.
I see the booking but the IoT unlock fails
This is not a Levy Bookings issue — the booking succeeded, but the IoT command failed. See IoT Troubleshooting for vehicle-side debugging.
Common cause: the vehicle's IoT device is offline. Check the vehicle status in Dashboard > Vehicles — if it shows red Offline, the unlock command cannot reach it. The booking is still valid; you may need to swap the assigned vehicle.