Build on the e-car.eth protocol.
REST, GraphQL, and WebSocket endpoints for vehicle identity, battery passports, payments, and OEM batch operations — all backed by Ethereum and ENS. Free Sepolia testnet access via wallet connect.
Overview #
The e-car.eth API is the developer-facing surface for the protocol's smart contracts on Ethereum Sepolia. It serves three audiences:
- OEMs — preauthorize vehicle batches, mint NFT identities, manage brand namespaces
- Operators — register charging stations, run sessions, settle V2G energy exports
- Developers — read vehicle, battery, and station data on-chain via a stable HTTP surface
https://earnest-harmony-e-car.up.railway.app — all routes under /api/v1/*5-min Quickstart #
From zero to a live on-chain read in five minutes.
1. Get an API key
Visit get-key.html and connect any Ethereum wallet — the key is issued instantly after one signature. No email, no waitlist.
2. Read a live Sepolia vehicle
# Vehicle #1 — Tesla Model 3 (2024), soulbound on Sepolia
curl https://earnest-harmony-e-car.up.railway.app/api/v1/vehicles/1 \
-H "x-api-key: ecar_fre_..."
3. You should see
{
"tokenId": "1",
"manufacturer": "Tesla",
"model": "Model 3",
"year": 2024,
"batteryCapacityKwh": "82000",
"locked": true,
"owner": "0x5f11a48230f7CdaB91A2361576239091E4b1165b"
}
That's it — you just did a live Ethereum read through a single HTTP call. From here you can register vehicles, preauthorize batches, or initiate charging payments. Pick your path below.
Authentication #
All write endpoints require an API key in the x-api-key header. Most read endpoints are public.
Wallet-gated self-serve (recommended)
Free tier: one key per wallet, 10K req/month, 60 req/min, Sepolia only.
# 1. Request a nonce + SIWE message bound to your address
curl https://earnest-harmony-e-car.up.railway.app/auth/nonce?address=0xYourAddr
# 2. Sign the returned `message` with your wallet (personal_sign / EIP-191)
# 3. POST the signature back to claim your key
curl -X POST https://earnest-harmony-e-car.up.railway.app/auth/keys/wallet \
-H "Content-Type: application/json" \
-d '{"address":"0x…","nonce":"…","signature":"0x…","message":"…"}'
The browser flow at get-key.html wraps this in a one-click experience via Reown AppKit.
OEM & Enterprise tier (admin-issued)
Paid tiers require manual approval. After your pilot is accepted, the team mints a key via the admin endpoint and sends it through a secure channel.
Inspect a key
curl https://earnest-harmony-e-car.up.railway.app/auth/keys/info \
-H "x-api-key: ecar_…"
Returns the tier, label, limits, monthly usage, and creation date.
Vehicle Identity #
Vehicles are minted as ERC-721 NFTs (with optional ERC-5192 soulbound lock) under the VehicleIdentity.sol contract. Each token stores a privacy-preserving VIN hash, manufacturer, model, year, and battery capacity.
Register a vehicle
curl -X POST https://earnest-harmony-e-car.up.railway.app/api/v1/vehicles \
-H "x-api-key: ecar_..." \
-H "Content-Type: application/json" \
-d '{
"vin": "5YJSA1H21FFP12345",
"manufacturer": "Tesla",
"model": "Model 3",
"year": 2024,
"batteryCapacityKwh": 82
}'
Returns an unsigned transaction the OEM signs and broadcasts with their wallet (or multisig). The VIN is stored on-chain as keccak256(VIN) — full VINs never leave the OEM's environment.
Merkle Batches — OEM Path #
The flagship OEM workflow. Submit up to 100,000 VINs in a single API call; the server builds a Merkle tree, returns the root + per-VIN proofs, and the OEM commits the root on-chain in one transaction. Each vehicle later claims its NFT individually using its proof.
Preauthorize 100K vehicles
curl -X POST …/api/v1/vehicles/batch/preauthorize \
-H "x-api-key: ecar_oem_…" \
-H "Content-Type: application/json" \
-d '{
"vins": ["5YJSA1H21FFP00001", ...],
"manufacturer": "Tesla",
"model": "Model 3",
"year": 2026,
"batteryCapacityKwh": 82,
"soulbound": true,
"overrides": [{ "vin": "5YJSA1H21FFP00002", "soulbound": false }]
}'
Response includes batchId, merkleRoot, per-soulbound counts, and an on-chain submission hint pointing at MerkleOracle.submitRoot(batchId, root).
Fetch a proof at claim time
curl …/api/v1/vehicles/batch/batch_a1b2.../proof/5YJSA1H21FFP00001
The buyer (or OEM frontend) reads this proof and calls the contract's claim method. Anyone can fetch a proof — the security model is the on-chain Merkle root, not API access.
Bulk transfer at delivery
curl -X POST …/api/v1/vehicles/batch/batch_a1b2.../transfer \
-H "x-api-key: ecar_oem_…" \
-d '{
"from": "0xOEM_TREASURY",
"transfers": [
{ "tokenId": "1", "to": "0xBUYER_A" },
{ "tokenId": "2", "to": "0xBUYER_B" }
]
}'
Returns up to 1,000 unsigned safeTransferFrom transactions at a time — multicall them on-chain for one-tx batch delivery.
Battery Passport #
The BatteryPassport.sol contract maintains an append-only on-chain history of each battery's state-of-health (SoH), cycle count, and a Merkle root anchoring off-chain telemetry. EU Battery Regulation 2023/1542 ready.
curl …/api/v1/battery/1
# { "vehicleId": "1", "stateOfHealth": 91, "cycleCount": 287,
# "merkleRoot": "0x9c014e…", "timestamp": "1774575252" }
Charging Sessions #
Register stations on-chain, initiate sessions with auto-escrowed funds, finalize with actual kWh, and settle instantly. Any token whitelisted by the operator works (ETH, USDC, or any ERC-20).
Brand Namespaces #
OEMs claim brand.e-car.eth via a 10 ETH one-time fee. The claim deploys a dedicated BrandRegistry + 2-of-2 multisig, granting full control over vehicle, station, and subname registration under that namespace.
Fleet Management #
Register multi-vehicle fleets under fleet.e-car.eth, attach geofence rules on-chain, and pull aggregated payment summaries across all vehicles + vendors.
Carbon Credits #
EV mileage → tokenized carbon credits (ERC-1155). Mint credits from oracle-attested odometer reads, retire them with on-chain certificates for ESG compliance, or trade them on any marketplace.
TypeScript SDK #
npm install @e-car-eth/sdk
import { ECarClient } from '@e-car-eth/sdk'
const client = new ECarClient({
apiKey: 'ecar_fre_…',
network: 'sepolia', // mainnet at pilot completion
})
// Live chain read
const vehicle = await client.vehicles.get(1n)
const passport = await client.battery.getPassport(1n)
const stations = await client.charging.listStations({ brand: 'tesla' })
// OEM batch path
const batch = await client.vehicles.preauthorize({
vins: vins100k,
manufacturer: 'Tesla', model: 'Model 3', year: 2026,
soulbound: true,
})
Voice SDK #
Drop-in adapter that converts natural language ("Charge to 80% with USDC") into on-chain transactions. Ships with Tesla-Grok, Alexa Auto, Google Assistant, and Siri/CarPlay platform adapters.
npm install @e-car-eth/voice-sdk
import { ECarVoicePlugin } from '@e-car-eth/voice-sdk'
const plugin = new ECarVoicePlugin({
vehicleId: 1n,
apiKey: process.env.ECAR_API_KEY,
adapter: 'tesla-grok', // alexa-auto | google-assistant | siri-carplay
})
const tts = await plugin.handleUtterance(
"Charge to 80% at the nearest Tesla station and pay with USDC"
)
Quickstart Bash Script #
A single bash file that exercises the full OEM path against any base URL — health, brand lookup, preauthorize, proof fetch, paginated proofs, bulk transfer, vehicle read, battery passport, station list. Useful as both a smoke check and a working example for integration teams.
# Get the script from the repo
curl -O https://raw.githubusercontent.com/RWA-ID/e-car-api/main/api/scripts/oem-quickstart.sh
chmod +x oem-quickstart.sh
# Run against any environment
API_BASE=https://earnest-harmony-e-car.up.railway.app \
API_KEY=ecar_fre_… \
BRAND=tesla \
./oem-quickstart.sh
Prints colored pass/fail per step and aborts on the first regression — drop it into CI for production smoke checks.
.http / Postman Collection #
A pre-filled REST Client collection (VS Code REST Client, JetBrains HTTP Client, Postman-importable) covering every key OEM endpoint. Variables for baseUrl, apiKey, brand, and wallet addresses are at the top of the file.
# Open in VS Code with the REST Client extension installed
curl -O https://raw.githubusercontent.com/RWA-ID/e-car-api/main/api/scripts/oem.http
code oem.http
WebSocket Events #
const ws = new WebSocket('wss://earnest-harmony-e-car.up.railway.app/ws')
ws.addEventListener('open', () => {
ws.send(JSON.stringify({
type: 'subscribe',
channels: ['vehicles', 'charging', 'battery'],
}))
})
ws.addEventListener('message', (e) => console.log(JSON.parse(e.data)))
// { type: 'vehicle:registered', tokenId: '2', manufacturer: 'Ford' }
// { type: 'session:started', sessionId: '...', stationNodeId: '0x...' }
// { type: 'battery:updated', vehicleId: '1', stateOfHealth: 91 }
GraphQL #
The GraphQL endpoint exposes the same data with field-level selection. Useful when a UI needs vehicle + passport + ownership in one round-trip.
POST /graphql
{
vehicle(tokenId: "1") {
manufacturer
model
locked
owner
batteryPassport { stateOfHealth cycleCount merkleRoot }
}
}
Error Codes #
| Status | Meaning | Typical fix |
|---|---|---|
400 | Bad request — missing or malformed field | Check the request body against the schema |
401 | Missing/invalid API key | Pass x-api-key header with a valid key |
404 | Resource not found (vehicle, batch, station) | Verify the ID is correct + exists on Sepolia |
429 | Rate limit exceeded | Back off, request OEM tier, or check the tier table |
500 | Server error | Retry; contact e-car@onchain-id.id if persistent |
Rate Limits #
| Tier | Monthly | Per minute | Network | Notes |
|---|---|---|---|---|
| Free | 10,000 | 60 | Sepolia | One key per wallet · self-serve |
| OEM | 5,000,000 | 1,000 | Sepolia (mainnet seat reserved) | Voice SDK · Brand namespace · 99.9% SLA |
| Enterprise | Unlimited | 5,000 | Multi-chain · custom | Dedicated RPC · white-label · 99.99% SLA |
Write endpoints (POST/PUT/PATCH/DELETE) have a stricter per-route ceiling of 10/minute on free tier — designed for OEM batch flows, not foot-gun loops.
Sepolia Contracts #
All 10 core contracts are source-verified on Sepolia. The API reads from these addresses directly via viem — no caching layer between you and the chain.
| Contract | Address |
|---|---|
VehicleIdentity | 0x54e0…41d1 |
BatteryPassport | 0x0931…4E15 |
UniversalPaymentEscrow | 0x7c9a…6c9f |
AgentWallet (impl) | 0x0a23…6f7f |
MerkleBatchOracle | 0x8d03…1982 |
NamespaceGovernorFactory | 0x9544…a89C |
MultiSigFactory | 0x5d10…00a9 |
ChargingStationRegistry | 0xfB91…46E5 |
ChargingPaymentRouter | 0x3aeC…2462 |
VoiceRampRouter | 0x3a1e…3080 |