Ride Packages
Ride packages are one-time prepaid bundles that provide customers with riding credits including time, unlocks, and distance. Unlike subscriptions which renew automatically, ride packages are purchased once and consumed until depleted.
Overview
Ride packages allow customers to pay upfront for a bundle of ride credits that they can use across one or more rides. This is ideal for occasional riders who want to prepay for convenience or save money compared to pay-per-ride pricing.
Key Features
- One-time purchase - No recurring charges or auto-renewal
- Flexible consumption - Use credits across multiple rides until depleted
- Included time - Minutes of riding included (configurable units: minutes, hours, days)
- Free unlocks - Optional unlock fee waiver
- Distance allowance - Optional included kilometers
- Pause minutes - Optional included pause time
- Group ride support - Packages can support multiple riders (max_riders)
- Location scoping - Packages can be location-specific or global
- Wallet or card payment - Customers can pay from wallet balance or credit card
Ride Packages vs. Subscriptions
| Feature | Ride Packages | Subscriptions |
|---|---|---|
| Billing | One-time | Recurring |
| Expiration | When depleted | Time-based (days) |
| Auto-renewal | No | Optional |
| Daily limits | No | Optional |
| Best for | Occasional riders | Regular commuters |
Accessing Ride Packages
Navigate to Pricing
Go to Dashboard and click Pricing in the sidebar navigation.
Find Packages Section
Scroll to the Ride Pricing Packages section.
Manage Packages
Click Add Package to create a new package or use edit/delete icons for existing ones.
Location-Specific
Ride packages are managed per-location. Switch to the appropriate subaccount before creating packages.
Package Configuration
Basic Information
Title (i18n)
The display name shown to customers, with translations for multiple languages.
| Field | Description | Example |
|---|---|---|
| English Title | Package name in English | "60 Minute Pack" |
| Spanish Title | Package name in Spanish | "Paquete de 60 Minutos" |
Best Practices:
- Include the primary benefit (time/unlocks) in the title
- Keep titles concise (2-4 words)
- Use consistent naming across packages
Description (i18n)
Optional extended description explaining package benefits.
| Field | Description | Example |
|---|---|---|
| English Description | Full details | "60 minutes of riding, use anytime" |
| Spanish Description | Full details | "60 minutos de viaje, usa cuando quieras" |
Step Number
Controls the display order in the mobile app.
| Value | Display Position |
|---|---|
| 1 | First (top) |
| 2 | Second |
| 3+ | Lower positions |
Lower numbers appear first. Highlight your best-value or most popular packages first.
Pricing
Price (Cents)
The amount customers pay for the package, stored in cents.
| Entry | Display |
|---|---|
| 499 | $4.99 |
| 999 | $9.99 |
| 1999 | $19.99 |
Pricing Tips:
- Calculate savings vs. pay-per-ride
- Offer clear value proposition
- Consider psychological price points ($X.99)
Included Benefits
Included Time
The primary benefit - riding time included in the package.
| Field | Description |
|---|---|
included_time_qty | Number of time units |
included_time_unit | Unit type: minutes, hours, or days |
Examples:
- 60 minutes = 1 hour of riding
- 2 hours = 120 minutes of riding
- 1 day = 24 hours of riding
Include Unlock Fee
Whether the package covers the unlock fee.
| Setting | Behavior |
|---|---|
| true | Package includes free unlock(s) |
| false | Customer pays unlock fee separately |
When enabled, the max_riders field determines how many free unlocks are included.
Included Distance (Optional)
Kilometers of distance included in the package.
| Value | Behavior |
|---|---|
| null | No distance included |
| 10 | 10 km included |
| 50 | 50 km included |
Distance Pricing
Distance allowances only apply when your pricing uses per-km charges. If using time-only pricing, this field has no effect.
Included Pause Minutes (Optional)
Minutes of paused time included.
| Value | Behavior |
|---|---|
| null | Pause fees charged normally |
| 30 | 30 pause minutes included |
| 60 | 60 pause minutes included |
Group Ride Support
Max Riders
Number of simultaneous riders the package supports.
| Value | Behavior |
|---|---|
| 1 | Single rider (default) |
| 2 | Pair riding |
| 4 | Small group |
Group Rides
When max_riders > 1, customers can start group rides with friends. Each rider in the group shares the package benefits. See Group Rides for more details.
Visual Customization
Badge Text
Optional badge to highlight the package.
| Value | Display |
|---|---|
| null | No badge |
| "BEST VALUE" | Badge on package |
| "POPULAR" | Badge on package |
Icon
Optional icon identifier for the package.
Is Popular
Flag to indicate this is a popular choice, may affect display styling.
Speed Limits
Max Speed (kph)
Optional speed limit applied during rides using this package.
| Value | Behavior |
|---|---|
| null | No speed restriction |
| 15 | Limited to 15 km/h |
| 20 | Limited to 20 km/h |
Useful for beginner packages or safety-focused offerings.
Creating a Ride Package
Step 1: Basic Setup
- Navigate to Pricing → Ride Pricing Packages
- Click Add Package
- Set Step Number for display order
- Enter Title in supported languages
Step 2: Pricing
- Enter Price in cents (e.g., 999 for $9.99)
- Select Currency (typically matches subaccount default)
Step 3: Time Allowance
- Enter Included Time Qty (e.g., 60)
- Select Included Time Unit (minutes, hours, or days)
Step 4: Additional Benefits
- Toggle Include Unlock Fee if package covers unlocks
- Set Max Riders if supporting group rides
- Add Included Distance if applicable
- Add Included Pause Minutes if applicable
Step 5: Customize & Activate
- Add optional Badge Text
- Toggle Activated to make available
- Click Save
How Packages Work
Purchase Flow
Customer Browses Packages
In the mobile app, customer views available packages for their location.
Select Package
Customer taps on a package to see details and purchase.
Choose Payment Method
Customer selects wallet balance or card payment.
Complete Purchase
For wallet: Immediate deduction. For card: Stripe PaymentIntent flow.
Package Activated
Credits are immediately available for use.
Usage During Rides
When a customer with an active package starts a ride:
- System checks for active package purchases
- Benefits applied - Unlock fee waived (if included), time starts counting against package
- During ride - Time/distance deducted from package allowances
- Ride ends - Remaining credits updated, excess charged normally
Package Consumption
Package: 60 Minutes
├── Ride 1: 15 minutes → 45 minutes remaining
├── Ride 2: 20 minutes → 25 minutes remaining
├── Ride 3: 30 minutes → Package depleted (5 min charged normally)
└── Status: Consumed
When a package is depleted, regular pricing applies for any excess usage.
Mobile App Integration
Package Display
The mobile app /packages screen shows:
- Available packages for the customer's location
- Package title (localized)
- Price formatted for currency
- Duration/time included
- Group ride indicator (if max_riders > 1)
- Purchase button
Active Packages
Customers can view their active packages:
- Package name and purchase date
- Remaining time/unlocks
- Location where package applies
- Usage history
Location Resolution
Packages are location-specific:
- App sends customer's GPS coordinates
- System checks which zones contain the location
- Matching subaccount's packages are displayed
- If ambiguous, customer may need to select location
API Reference
GET /api/mobile/packages
Fetch available packages for a location.
Query Parameters:
lat- Latitude (optional)lng- Longitude (optional)subaccount_id- Direct subaccount ID (optional)
Response:
{
"data": {
"purchases": [...],
"available_packages": [...],
"has_active_package": false,
"location": {
"subaccount_id": "uuid",
"subaccount": { "name": "City Name" }
}
}
}
POST /api/mobile/packages
Purchase a package.
Request Body:
{
"package_id": "uuid",
"payment_method": "wallet"
}
Response (wallet payment):
{
"data": { ... purchase record ... },
"payment": {
"method": "wallet",
"amount_cents": 999,
"new_wallet_balance_cents": 1501
}
}
Response (card payment required):
{
"requires_payment": true,
"client_secret": "pi_..._secret_...",
"payment_intent_id": "pi_...",
"amount_cents": 999
}
Database Schema
Table: ride_pricing_packages
| Column | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
subaccount_id | UUID | Location scope |
step_number | Integer | Display order |
title_i18n | JSONB | Localized titles |
description_i18n | JSONB | Localized descriptions |
price_cents | Integer | Package price |
currency | Text | Currency code (USD) |
activated | Boolean | Available for purchase |
include_unlock_fee | Boolean | Unlock fee included |
included_time_qty | Integer | Time amount |
included_time_unit | Text | minutes/hours/days |
included_distance_km | Integer | Distance included |
included_pause_minutes | Integer | Pause time included |
max_riders | Integer | Group ride support |
max_speed_kph | Integer | Speed limit (optional) |
badge_text | Text | Display badge |
is_popular | Boolean | Popular flag |
deleted_at | Timestamp | Soft delete |
Table: ride_pricing_package_purchases
| Column | Type | Description |
|---|---|---|
id | UUID | Unique identifier |
customer_uuid | UUID | Customer reference |
package_id | UUID | Package reference |
subaccount_id | UUID | Purchase location |
status | Text | active/consumed |
package_snapshot | JSONB | Package at purchase time |
purchased_at | Timestamp | Purchase time |
remaining_time_minutes | Integer | Time remaining |
remaining_unlocks | Integer | Unlocks remaining |
remaining_distance_km | Decimal | Distance remaining |
remaining_pause_minutes | Integer | Pause time remaining |
Common Scenarios
Scenario 1: Basic Time Package
Goal: Simple 1-hour ride package
Setup:
- Title: "1 Hour Pack"
- Price: $9.99 (999 cents)
- Time: 60 minutes
- Include Unlock: Yes
- Max Riders: 1
Customer Value: Saves vs. unlock fee + hourly rate
Scenario 2: Group Day Pass
Goal: Family/friends day out
Setup:
- Title: "Group Day Pass"
- Price: $29.99 (2999 cents)
- Time: 4 hours
- Include Unlock: Yes
- Max Riders: 4
- Badge: "BEST FOR GROUPS"
Customer Value: 4 people can ride together sharing the time
Scenario 3: Distance Package
Goal: Tour/exploration package
Setup:
- Title: "Explorer 50km"
- Price: $24.99 (2499 cents)
- Time: 2 hours
- Distance: 50 km
- Include Unlock: Yes
Customer Value: Good for touring with distance cap
Best Practices
Package Design
- Clear value proposition - Make savings obvious
- Tiered options - Small, medium, large packages
- Match use cases - Commute, recreation, tourism
- Group options - Families, friends, tourists
Pricing Strategy
- Calculate break-even - When does package save money?
- Anchor pricing - Show per-minute equivalent
- Bundle value - Combine time + unlocks + pause
Display Optimization
- Best value first - Use step_number strategically
- Use badges - Highlight popular/recommended
- Clear descriptions - Explain what's included
Troubleshooting
Package Not Visible
- Check
activatedis true - Verify
deleted_atis null - Confirm correct subaccount selected
- Check customer's location matches package subaccount
Credits Not Applying
- Verify purchase status is 'active'
- Check remaining credits aren't zero
- Confirm package subaccount matches ride location
- Review ride pricing calculation logs
Group Ride Issues
- Check
max_riderssetting - Verify group rides enabled in subaccount settings
- Confirm package has remaining unlocks
Packages Configured
With ride packages in place, customers can prepay for ride credits and enjoy simpler, more predictable pricing. Monitor package sales and usage to optimize your offerings.