Transit trip planning and live delay snapshots, straight from open GTFS and GTFS-Realtime feeds. One paid HTTP call, answer in the response body. Pay in USDC on Base or Solana — your client picks the rail.
git clone https://github.com/nirholas/x402-transit && cd x402-transit && npm install && npm run dev| Route | Price | You get back |
|---|---|---|
GET /plan | $0.002 | Itinerary options — legs, routes, scheduled times, and realtime predictions where the feed has them |
GET /delays | $0.001 | Live delay snapshot for a stop: prediction minus schedule per arrival, plus a summary verdict |
GET /health | free | Feed and agency in use |
GET /stops | free | Search stops by name — never pay to find a stop id |
GET /routes | free | Routes, optionally just those at one stop |
GET /.well-known/x402 | free | Machine-readable price sheet, both rails |
Resolving stops and routes is free. Only planning and delay lookups cost, and a delay look is a tenth of a cent — cheap enough to poll, so bound the loop yourself.
Every 402 lists both networks. A caller holding USDC on Base pays on Base; a caller holding USDC on Solana pays on Solana. Same route, same price, same artifact.
base-sepolia by default, base for mainnet. EIP-3009 transfer authorization.
0x40252CFDF8B20Ed757D61ff157719F33Ec332402
solana mainnet by default, solana-devnet for testing. SPL transfer.
WwwuGbqHrwF5RG89KhUbmRWEvjnRH9k5kVM5p7T3WwW
X-PAYMENT# 1. Run the service (works immediately — the feed is keyless)
cp .env.example .env
npm run dev # http://localhost:4024
# 2. Free: find a stop id
curl -s "http://localhost:4024/stops?query=Porter" | jq '.stops[0]'
# 3. See the dual-rail 402 quote (no wallet needed)
curl -s "http://localhost:4024/plan?from=South%20Station&to=Porter" \
| jq '.accepts[] | {network, payTo, maxAmountRequired}'
# 4. Pay for real on Base Sepolia (free test USDC: faucet.circle.com)
export PRIVATE_KEY=0x…
npm run client # plans a trip, then checks live delays
The feeds here are public and keyless, so they are called live with no signup.
The default agency is the MBTA, whose V3 API is a JSON projection of its GTFS static
feed plus GTFS-Realtime TripUpdates. Point GTFS_API_BASE at another
agency running the same API to switch cities.
There is deliberately no fixture fallback. If the feed is unreachable you get a
502, never invented departure times — a wrong train time is worse than no
train time. For the same reason, /plan marks each leg
realtime: true|false so you know whether a prediction is live or just the
timetable, and /delays reports status: "unknown" for added
service that has no schedule to be measured against.