Driver onboarding in BetterSuite has two surfaces and a real state machine. There's the admin-side flow in the Ops Console (Taxi → Drivers) where you create or review drivers, and there's the driver-app side where the person uploads their own documents. They meet in the middle at the pending verification review screen.
The actual driver state machine
DriverStatus is defined in backend/crates/core/kernel/src/driver_status.rs:
| Status | When a driver lands here |
|---|---|
Pending | Newly registered driver, hasn't submitted vehicle details yet. |
PendingReview | Driver has submitted vehicle details and is waiting on admin review. |
Approved | Verified driver who can go online and take trips. |
Suspended | Temporarily blocked. |
Blocked | Permanently banned. |
Archived | Deleted / inactive. |
A driver needs Approved status to go online. Approving a driver also approves their KYC application (see Step 3).
Step 1: Get drivers into the system
There are two ways a driver record gets created.
A. Admin-created from the Ops Console
In Taxi → Drivers → Add new driver (the CreateNewDriverScreen), you fill in two steps via an AppHorizontalStepIndicator:
Step 1 — Details
| Field | Notes |
|---|---|
| Profile picture | Required (uses UploadFieldSmall with a required validator). |
| First name | Required. |
| Last name | Required. |
| Phone | Required; defaults to your tenant's default country code. |
| Optional, but you must provide at least email or phone. | |
| Gender | Required dropdown over Enum$Gender. |
| Car Make / Model / Color | Selected from your Vehicle Catalog (the model dropdown is disabled until you pick a make). |
| Car production year | Integer. |
| Car plate number | String. |
The Details step has a documents tab in the code but it's currently commented out — admin-created drivers don't upload documents from this screen.
Step 2 — Service Pricing
You pick which service classes this driver is eligible for from the tenant's catalog (the list comes from serviceClassesAdmin). The selection is saved as INCLUDE rows in taxi.driver_service_class via the setDriverServiceClasses mutation.
Behind the scenes, the createDriver mutation (in backend/crates/taxi/application/src/driver_admin/driver_admin_mutation.rs):
- Looks for an existing account with that email or phone and reuses it, otherwise creates a new account on your tenant.
- Grants the Driver role.
- Creates a driver record bound to that account.
The newly created driver lands at Pending status. Service-class assignments are written but the driver still needs the rest of their KYC flow before they can go online.
B. Driver-app self-registration
A driver can also install the BetterTaxi driver app, sign in with phone + OTP, and complete the onboarding themselves. The app's KYC step (frontend/apps/taxi_driver/lib/features/kyc/presentation/widgets/kyc_documents_widget.dart) fetches the tenant's KYC requirements, creates a draft KycApplication, and walks the driver through uploading one document per requirement plus a FACE_MATCH selfie used as the profile picture.
Two important details:
- If the tenant has no KYC policy for the (App=Taxi, Role=Driver) combination, the driver app shows a "No KYC documents required for your account" screen and the application step is skipped.
- If the tenant is flagged as a demo / test tenant (
isDemofrom theTenantCubit), the UI shows a banner explaining that uploads will be auto-approved for testing purposes.
Step 2: Configure KYC requirements (once per tenant)
The documents a driver has to upload are not hard-coded — they come from your tenant's KYC policy. The relevant entities live in backend/crates/kyc/domain/:
KycPolicyEntityis keyed by(tenant_id?, vertical, role, country?). Tenant-specific policies override the platform default. Policies are versioned (policy_key+version).- A policy holds a list of requirements, each pointing at a
KycCheckKind.
The available check kinds (kyc_check_kind_enum.rs) are:
| Kind | Purpose |
|---|---|
GovId | National ID or passport. |
DriverLicense | Driver's license — relevant for taxi / courier roles. |
AddressProof | Utility bill, bank statement, etc. |
FaceMatch | Selfie matched against a photo on a document. |
Liveness | Video liveness check. |
VehicleRegistration | Vehicle registration documents. |
VehicleInsurance | Vehicle insurance proof. |
BusinessRegistration | Used for KYB / business registration. |
UboDeclaration | Ultimate beneficial owner declaration. |
BankAccountVerification | Bank account proof. |
FoodLicense | Food handling license (F&B merchants). |
ProfessionalLicense | Trade-specific licenses (electrician, plumber, etc.). |
You manage policies in Management Common → KYC → Policies (the KycPoliciesListScreen / KycPolicyDetailsScreen pair). Each policy carries vertical (App), role (RoleKind), optional country, a min_level, and an active flag.
You can also manage Certifications (tenant-defined KycRequirement rows) in Management Common → KYC → Certifications and reference them in a Service Class's Compliance section ("Required certifications" multi-select). A driver who hasn't uploaded an approved document for a required certification can't go online for that service class.
Step 3: Review and approve
When a driver finishes uploading documents in the driver app, the KYC application moves from Draft to Pending (backend/crates/kyc/domain/src/application_status_enum.rs), and the driver shows up in:
Taxi → Drivers → Approvals(the Pending Verification list,DriverPendingVerificationListScreen).Management Common → KYC → Applications(the cross-vertical KYC queue,KycApplicationsListScreen).
Clicking a driver in the Approvals list opens DriverPendingVerificationReviewScreen, organized into three collapsible sections:
- Personal information — name, contact, vehicle details (these are editable here).
- Documents — each uploaded
KycDocumentappears as an image preview with two reviewer inputs: an expire date (expiresAt) and a retention policy picked from the tenant'sRetentionPolicycatalog. - Service Pricing — confirm the service classes this driver is eligible for.
The bottom action bar has three buttons:
| Action | Effect |
|---|---|
| Hard reject | Opens a rejection dialog (reason + internal staff note). Permanent rejection. |
| Soft reject | Same dialog, treated as a fixable rejection (the driver gets a message and can re-submit). |
| Approve | Runs approveDriver — sets DriverStatus = Approved and approves the underlying KYC application via the KYC service. |
The rejection dialog (DriverPendingVerificationReviewRejctionDialog) collects two messages:
- Rejection message to driver — sent to the driver.
- Rejection message to staff — internal note, visible to ops staff only.
For deeper KYC-only review (e.g., to see the OCR breakdown, override DocumentStatus per document, or set per-document retention), open the application directly from Management Common → KYC → Applications → [application]. That screen exposes the AI OCR panel and finer-grained controls.
What we don't have
The previous version of this article promised a few things that aren't in the product. Don't go looking for them:
- No bulk-import CSV for drivers.
createDriveris single-driver. If you need to migrate a fleet, use theMigrationsrunner in the Owner Dashboard (/dashboard/migrations) — that has the bulk import pipelines. - No "kiosk mode" for in-person onboarding. There's no tablet-friendly batch UI for walking drivers through registration in person. You can run an event by sitting drivers down with their own phones and creating the records one at a time via either the admin Create flow or driver self-signup.
- No "generate registration link with your tenant slug" feature. Drivers find your tenant in the driver app via tenant discovery (the same flow as the Ops Console login), not a magic link.
- No automatic KYC scoring shown in the queue. What you see in the review screen is the documents and their
DocumentStatus, not a provider-side fraud score.
Driver app — once approved
Once a driver is Approved, the BetterTaxi driver app surfaces:
- Status — go online / offline.
- Earnings — per-period earnings with charts.
- Ride history — past trips.
- Wallet — driver wallet balance and transactions.
- Payout methods — bank or mobile-wallet accounts they get paid into.
- Vehicle — their registered vehicle.
- Profile, settings, requirements — the rest of the self-service surface.
Folder reference: frontend/apps/taxi_driver/lib/features/.
What's next
- Set Up Your Fleet — if your service classes or pricing aren't ready yet, drivers can't be assigned to anything useful.
- Dashboard Tour — the Approvals list is in the Ops Console under Taxi; KYC policies are in Management Common.
- Plans & Billing — your plan caps how many cities (and therefore how many distinct local rosters) you can operate.