Developing a Mobile App for Bus Tickets
Bus transport market in Russia—thousands of carriers with different accounting systems, no unified API, and aggregators with questionable schedule accuracy. This makes bus ticketing more complex than aviation, despite seeming simplicity.
Data Sources and Integration
Three main paths:
Carrier's Own System. Develop for specific carrier—they have their own schedule and cash system (usually Avtovokzal, Radar, Transinfo or 1C). Integrate directly via REST or XML API. Reliable but closed audience.
Aggregators. Tutu.ru, Busfor, CheckMyBus provide API for white-label partners. Access via contract. Tutu API—REST/JSON, current schedules for most Russian and CIS routes. CheckMyBus for international routes.
Own Aggregation. Parsing and direct contracts with carriers—most expensive and labor-intensive option, but gives data control and margin.
Search and Seat Availability
Search: from-to, date, passenger count. Stop autocomplete via UISearchTextField (iOS) with 300ms debounce or SearchBar + Flow in Jetpack Compose. Stop database cached locally: full list of Russian bus terminals—about 3000 records, load on first run and update weekly.
Seat selection. Not all carriers support bus cabin schema with specific seat selection—some just sell "a seat on the bus." When schema available, render as rows by rows and cols from API, mark occupied.
// SwiftUI: bus seat grid
struct BusSeatMapView: View {
let seats: [[BusSeat?]] // nil = aisle
var body: some View {
VStack(spacing: 4) {
ForEach(seats.indices, id: \.self) { row in
HStack(spacing: 4) {
ForEach(seats[row].indices, id: \.self) { col in
if let seat = seats[row][col] {
SeatCell(seat: seat)
} else {
Spacer().frame(width: 32)
}
}
}
}
}
}
}
E-ticket
After payment—generate PDF with ticket QR. Important: some carriers don't accept e-tickets—only printed. Must explicitly show this limitation in UI before purchase, otherwise negative reviews flood in.
QR stored in FileManager (iOS) / filesDir (Android) for offline access. Push notification 2 hours before departure via FCM/APNs.
Payment
SBP is main payment method for bus tickets: low commission, instant credit. YooKassa or CloudPayments for cards. Apple Pay and Google Pay boost conversion on final step—don't forget them.
For some carriers—cash payment at boarding: book without payment with 30-minute hold. Hold scheme not needed; just payment_method: cash flag in booking.
Ticket Refund
Refund via carrier or aggregator API. Conditions differ for all—display on purchase screen, don't hide in terms. Technically: DELETE /orders/{id} or POST /orders/{id}/refund. Money returns to card in 3–10 business days depending on bank.
Typical policy: free cancellation 3+ hours before departure, 10–30% penalty for cancellation under 3 hours. Specific conditions come from API with schedule.
Notifications and Tracking
Track delays via carrier API if supported, or periodic route status polling. Push 2 hours and 30 minutes before departure. If carrier supports GPS tracking—show current bus position on map via MapKit / Google Maps SDK.
Timeline
4–6 weeks for app for specific carrier or with aggregator API. Pricing is calculated individually after requirements analysis.







