BetterTaxi: Onboard Drivers

How drivers move from \"created\" to \"approved\" in the Ops Console — the actual KYC pipeline, document review, and approval flow.

Last updated May 19, 2026

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:

StatusWhen a driver lands here
PendingNewly registered driver, hasn't submitted vehicle details yet.
PendingReviewDriver has submitted vehicle details and is waiting on admin review.
ApprovedVerified driver who can go online and take trips.
SuspendedTemporarily blocked.
BlockedPermanently banned.
ArchivedDeleted / 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

FieldNotes
Profile pictureRequired (uses UploadFieldSmall with a required validator).
First nameRequired.
Last nameRequired.
PhoneRequired; defaults to your tenant's default country code.
EmailOptional, but you must provide at least email or phone.
GenderRequired dropdown over Enum$Gender.
Car Make / Model / ColorSelected from your Vehicle Catalog (the model dropdown is disabled until you pick a make).
Car production yearInteger.
Car plate numberString.

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):

  1. Looks for an existing account with that email or phone and reuses it, otherwise creates a new account on your tenant.
  2. Grants the Driver role.
  3. 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 (isDemo from the TenantCubit), 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/:

  • KycPolicyEntity is 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:

KindPurpose
GovIdNational ID or passport.
DriverLicenseDriver's license — relevant for taxi / courier roles.
AddressProofUtility bill, bank statement, etc.
FaceMatchSelfie matched against a photo on a document.
LivenessVideo liveness check.
VehicleRegistrationVehicle registration documents.
VehicleInsuranceVehicle insurance proof.
BusinessRegistrationUsed for KYB / business registration.
UboDeclarationUltimate beneficial owner declaration.
BankAccountVerificationBank account proof.
FoodLicenseFood handling license (F&B merchants).
ProfessionalLicenseTrade-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:

  1. Personal information — name, contact, vehicle details (these are editable here).
  2. Documents — each uploaded KycDocument appears as an image preview with two reviewer inputs: an expire date (expiresAt) and a retention policy picked from the tenant's RetentionPolicy catalog.
  3. Service Pricing — confirm the service classes this driver is eligible for.

The bottom action bar has three buttons:

ActionEffect
Hard rejectOpens a rejection dialog (reason + internal staff note). Permanent rejection.
Soft rejectSame dialog, treated as a fixable rejection (the driver gets a message and can re-submit).
ApproveRuns 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. createDriver is single-driver. If you need to migrate a fleet, use the Migrations runner 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.

Build the foundation once. Expand without limits.

BetterSuite is built for teams who see on-demand as a business — not a feature.