_Docs/
Get StartedModulesPlatformDeployCookbookChangelogReference
_Cookbook
  • Introduction
    • RideShare Tutorial
    • Omnibus Account Management
    • Payment Card Acceptance Processing
    • Card Issuing & Financial Host
    • Stablecoin On-Ramp & Off-Ramp Operations
    • Stablecoin Issuer
    • Neobank (FBO)
    • Marketplace Payouts
    • Crypto Custody
    • BNPL & Lending
  1. Examples
  2. Getting Started
  3. RideShare Tutorial
Cookbook

RideShare Tutorial

In this tutorial, we will set up and use Formance Ledger for a ride-sharing platform called "RideShare." We will design a Chart of Accounts, create a schema to enforce it, use Numscript to execute transactions, and check account balances.

Prerequisites
fctl CLI installedA sandbox stack created

The Complete Schema#

Here is the full ledger schema for the RideShare tutorial. It defines the account hierarchy and all four transaction patterns we'll walk through below.

worldaccount
└─ paymentaccount
├─ mainaccount
└─ feesaccount
│ └─ {}$ride_idaccount
└─ mainaccount
Open in Studio

Edit this template in the Formance Studio editor.

Open in Studio

Design the Chart of Accounts#

The Chart of Accounts should reflect all account types relevant to your flow of funds and reporting needs.

We recommend starting with the key questions you need the ledger to answer. For RideShare:

  • How much did we pay the drivers?
  • How much did we collect in service fees?
  • How much did an individual rider pay?
  • How much did an individual driver earn?

And key events the ledger must support:

  • Rider books a ride
  • RideShare confirms the ride
  • Driver finishes the ride
  • RideShare completes ride verification
  • Driver requests earnings withdrawal

The schema defines four account groups to support these questions and events:

World#

worldaccount

The @world account represents the external world — funds entering and exiting the ledger.

Rider#

└─ paymentaccount

Each rider gets a per-ride payment account (rider:$rider_id:ride:$ride_id:payment) that records the estimated charge for that ride.

Ride#

├─ mainaccount
└─ feesaccount

Each ride has a main account (total charged) and a fees account (RideShare's service fee).

Driver#

│ └─ {}$ride_idaccount
└─ mainaccount

Each driver has per-ride earning accounts and a main account that accumulates total earnings across rides.

The structured naming convention helps organize accounts into segments, making it easier to manage and query them.

Create the Schema#

Now let's create the schema to enforce the Chart of Accounts. First, get your sandbox API endpoint:

bash
fctl stack show

Then create the schema using the API. You can copy the YAML from the schema viewer above, or use the JSON equivalent:

curl -X POST $FORMANCE_API_URL/api/ledger/v2/default/schemas/v1.0.0 \
  -H "Content-Type: application/json" \
  -d '{
    "chart": {
      "world": {},
      "rider": {
        "$rider_id": {
          "ride": {
            "$ride_id": {
              "payment": {}
            }
          }
        }
      },
      "ride": {
        "$ride_id": {
          "main": {},
          "fees": {}
        }
      },
      "driver": {
        "$driver_id": {
          "ride": {
            "$ride_id": {}
          },
          "main": {}
        }
      }
    },
    "transactions": {}
  }'
POST/api/ledger/v2/default/schemas/v1.0.0

By default, the ledger runs in audit mode—transactions are validated against your schema but allowed through. For strict enforcement, see enforcement modes.

Introduce Money into the Ledger#

When a rider books a ride, we record the estimated payment from @world into the rider's ride payment account.

RIDE_BOOKING
experimental
account interpolation
Rider books a ride. Record the estimated payment from the external world into the rider's ride payment account.
#![feature("experimental-account-interpolation")]
vars {
    number $amount
    account $rider_id
    account $ride_id
}

send [USD/2 $amount] (
    source = @world
    destination = @rider:$rider_id:ride:$ride_id:payment
)

Execute this transaction:

fctl ledger transactions num intro.num
POST/api/ledger/v2/default/transactions

This adds $20 to the @rider:xx:ride:yy:payment account.

Run Transactions on the Ledger#

Ride Confirmation#

When RideShare confirms the ride, transfer the payment from the rider's account to the ride's main account.

RIDE_CONFIRMATION
experimental
account interpolation
RideShare confirms the ride. Transfer the recorded amount from the rider's payment account to the ride's main account.
#![feature("experimental-account-interpolation")]
vars {
    number $amount
    account $rider_id
    account $ride_id
}

send [USD/2 $amount] (
    source = @rider:$rider_id:ride:$ride_id:payment
    destination = @ride:$ride_id:main
)
fctl ledger transactions num payment.num
POST/api/ledger/v2/default/transactions

Ride Completion#

After the ride is completed, split the payment between the driver's earnings and RideShare's service fees.

RIDE_COMPLETION
experimental
account interpolation
Driver finishes the ride and RideShare verifies it. Split the payment between the driver's earnings and RideShare's service fees.
#![feature("experimental-account-interpolation")]
vars {
    number $amount
    account $ride_id
    account $driver_id
}

send [USD/2 $amount] (
    source = @ride:$ride_id:main
    destination = {
        10% to @ride:$ride_id:fees
        remaining to @driver:$driver_id:main
    }
)
fctl ledger transactions num payment_split.num
POST/api/ledger/v2/default/transactions

Driver Payout#

After some days, the driver requests their earnings. Transfer all accumulated earnings back to @world to represent funds leaving the ledger. The wildcard * sends the entire balance.

DRIVER_PAYOUT
experimental
account interpolation
Driver requests withdrawal. Transfer all accumulated earnings back to the external world.
#![feature("experimental-account-interpolation")]
vars {
    account $driver_id
}

send [USD/2 *] (
    source = @driver:$driver_id:main
    destination = @world
)
fctl ledger transactions num driver_payment.num
POST/api/ledger/v2/default/transactions

Check Account Balances#

You can check the balances of the accounts using the Formance Console.

IntroductionOmnibus Account Management
On This Page
  • The Complete Schema
  • Design the Chart of Accounts
  • World
  • Rider
  • Ride
  • Driver
  • Create the Schema
  • Introduce Money into the Ledger
  • Run Transactions on the Ledger
  • Ride Confirmation
  • Ride Completion
  • Driver Payout
  • Check Account Balances