data.object is the resource as the API returns it from the matching GET, frozen at the moment the event was created.
Envelope
(The envelope sample above abbreviates
data.object.)
Events fire for changes made through any channel: the fleet portal, the driver app, the chargers and the API. New event types may be added to v1; endpoints subscribed to * will receive them, so ignore types you don’t handle.
All event types
Sessions
Session started
session.started · data.object: Session
A fleet-wallet session has started: the charger reported the start of the transaction. Fires for sessions started from the API, the driver app or the charger.
session.started
Session start failed
session.start_failed · data.object: Session
A session never charged: the charger rejected the start, or the start was abandoned (for example, the cable was never plugged in). The wallet reservation is released and nothing is billed. status is cancelled.
session.start_failed
Session completed
session.completed · data.object: Session
A session has been settled and its final energy and cost are known. Fires however the session ended: a stop from the API or app, the driver unplugging, the budget being reached, or a later reconciliation.
session.completed
Session stopped by limit
session.stopped_by_limit · data.object: Session, plus stop_reason: "budget_reached"
A session used up its energy budget (its max_kwh, a fleet or driver limit, or what the wallet could cover), so ChargeExpress asked the charger to stop. Sent once per session. session.completed follows when the charger confirms.
session.stopped_by_limit
Wallet
Wallet funded
wallet.funded · data.object: Funding
A top-up has been paid and the wallet credited. Any outstanding credit is repaid first (debt_repaid), and the rest is credited as kWh (credited_kwh). Fires for top-ups started in the portal too.
wallet.funded
Wallet funding failed
wallet.funding_failed · data.object: Funding
The payment provider reported that a top-up failed. Nothing was credited.
wallet.funding_failed
Wallet low balance
wallet.low_balance · data.object: Wallet, plus low_balance_threshold_kwh
The wallet’s balance_kwh dropped below the fleet’s low_balance_threshold_kwh (set with PATCH /fleet). Fires once when the balance crosses the threshold, and again only after the balance has been back at or above it.
wallet.low_balance
Invoices
Invoice created
invoice.created · data.object: Invoice (kind: "usage" or kind: "purchase")
ChargeExpress has assigned an invoice number. A usage invoice bills the part of a completed session that went on credit; its id is the session id. A purchase invoice covers a paid top-up; its id is the funding id.
Invoice paid
invoice.paid · data.object: Invoice (kind: "usage")
A usage invoice has been fully repaid, by POST /invoices/usage/pay or by any top-up, which repays outstanding credit first. Purchase invoices are paid when created, so they never send this event.
invoice.paid
Drivers
Driver created
driver.created · data.object: Driver
A driver was added to the fleet, from the API or the portal.
driver.created
Driver updated
driver.updated · data.object: Driver
A driver’s details or status changed, including suspension (status: "suspended"), reactivation and photo uploads.
driver.updated
Driver removed
driver.removed · data.object: Driver
A driver was removed from the fleet. The driver record is kept with status: "archived", and their vehicles are unassigned.
driver.removed
Vehicles
Vehicle created
vehicle.created · data.object: Vehicle
A vehicle was added to the fleet.
vehicle.created
Vehicle updated
vehicle.updated · data.object: Vehicle
A vehicle’s details, status or assigned driver changed.
vehicle.updated
Vehicle retired
vehicle.retired · data.object: Vehicle
A vehicle was retired (status: "retired"), for example with DELETE /vehicles/{vehicleId}. Its driver is unassigned and its history is kept.
vehicle.retired
Invitations
Invitation accepted
invitation.accepted · data.object: Invitation, with the resulting driver
Someone accepted an invitation to join the fleet in the ChargeExpress app and is now a driver. Invitations themselves are managed in the portal, not the API.
invitation.accepted
Limits
Limits updated
limit.updated · data.object: Limit set
The fleet’s default limits (scope: "fleet", driver_id: null) or one driver’s overrides (scope: "driver") were replaced. limits is the complete new set for that scope. An override with amount: null exempts the driver from that fleet default. Each limit’s source matches the scope: "fleet" for defaults, "driver" for overrides.
limit.updated
Limit reached
limit.reached · data.object: Limit reached
A fleet or driver limit affected a session start. outcome: "capped" means the session started with a smaller budget (allowed_kwh) than requested. outcome: "blocked" means the limit was already used up and the start was refused. limit is the limit that applied, with its usage in the current period. requested_kwh is null when no max_kwh was requested.
limit.reached
Ping
ping is sent only by Send test in the portal and by POST /webhook_endpoints/{endpointId}/test when no type is given. It is signed like any other event, but it isn’t stored, retried or listed in /events, and you can’t subscribe to it.
Send test can also send any type on this page: pass {"type": "wallet.funded"} (for example) and the endpoint receives a sample event of that type, with the same shape as the samples here. Like ping, test events aren’t stored or retried. See Testing an endpoint.
ping

