Sync vehicles with your ERP
Most organizations keep vehicles in an ERP or asset register (Odoo, SAP, Dynamics, Sage) as well as in Fleet. This recipe keeps them aligned: the ERP owns purchase data, Fleet owns operational status and meters.
Scopes: vehicles:write, branches:read.
ERP → Fleet: upsert by fleet number
Section titled “ERP → Fleet: upsert by fleet number”Use the ERP’s asset number as Fleet’s vehicle_number, which must be unique. Look the vehicle up by it, then
update it or create it.
const API = 'https://api.get-fleet.com/v1'const headers = { Authorization: `Bearer ${process.env.FLEET_API_KEY}`, 'Content-Type': 'application/json' }
async function upsertVehicle(asset, retried = false) { const fields = { vehicle_number: asset.number, name: asset.description, make: asset.make, model: asset.model, year: asset.year, vin: asset.chassis_number, license_plate: asset.registration, purchase_date: asset.acquired_on, // "2024-03-15" purchase_price: asset.cost, // "4250000.00" purchase_currency: asset.currency, } const found = await (await fetch(`${API}/vehicles?vehicle_number=${encodeURIComponent(asset.number)}`, { headers })).json() if (found.data.length === 0) { const res = await fetch(`${API}/vehicles`, { method: 'POST', headers: { ...headers, 'Idempotency-Key': `asset-${asset.number}-create` }, body: JSON.stringify(fields), }) // 409: the number was taken between the lookup and the create. Look it up once more and update instead. if (res.status === 409 && !retried) return upsertVehicle(asset, true) if (!res.ok) throw new Error(`${asset.number}: ${(await res.json()).code}`) return res.json() } const { vehicle_number, ...changes } = fields const res = await fetch(`${API}/vehicles/${found.data[0].id}`, { method: 'PATCH', headers, body: JSON.stringify(changes) }) return res.json()}Map branches by listing GET /v1/branches once and matching on code, then send branch_id.
To retire a vehicle, set "status": "disposed". Fleet keeps its history; vehicles are not deleted through the API.
Fleet → ERP: incremental pull
Section titled “Fleet → ERP: incremental pull”Pull changes since your last run and write the fields Fleet owns (status, meters) back to the ERP:
let since = await loadCheckpoint() // e.g. "2026-11-01T00:00:00.000Z"let cursordo { const url = new URL(`${API}/vehicles`) url.search = new URLSearchParams({ updated_since: since, sort: 'updated_at', limit: '100', ...(cursor && { cursor }) }) const page = await (await fetch(url, { headers })).json() for (const v of page.data) { await erp.updateAsset(v.vehicle_number, { status: v.status, odometer: v.meters.primary.reading }) since = v.updated_at } cursor = page.next_cursor} while (cursor)await saveCheckpoint(since)If people edit vehicles in Fleet and the ERP pushes changes at the same time, send the ETag you read as
If-Match on your PATCH. A 412 means someone changed the vehicle in between: read it again and reapply.