What cancel is for
cancel ends an order before the service is delivered. A driver books a charger, their plans change, they cancel. The connector is released, any hold is lifted, and a fee may apply depending on how far the order had progressed.
The boundary against update is firm: if energy has flowed, cancel is the wrong action. A partially delivered charge has to be completed and billed for what was consumed, not voided.
The request
POST https://cpo.electreefi.in/beckn/cancel
{
"context": {
"domain": "ev-charging:uei", "action": "cancel", "version": "1.1.0",
"bap_id": "emsp.example.com", "bap_uri": "https://emsp.example.com/beckn",
"bpp_id": "cpo.electreefi.in", "bpp_uri": "https://cpo.electreefi.in/beckn",
"transaction_id": "txn-4471", "message_id": "msg-9051",
"timestamp": "2026-08-11T09:28:00Z"
},
"message": {
"order_id": "ord-EFI-2026-0811-4471",
"cancellation_reason_id": "4",
"descriptor": { "short_desc": "Driver no longer travelling to this location" }
}
}cancellation_reason_id refers to a network-defined list rather than free text, so reasons can be aggregated across the whole network. A BAP discovers the valid list from the BPP before offering choices to a driver, rather than inventing its own codes.
The free-text descriptor is supplementary. Do not put anything a system needs to act on in there — it is for humans reading a support ticket.
The response
POST https://emsp.example.com/beckn/on_cancel
{
"context": { "...": "same transaction_id", "action": "on_cancel",
"message_id": "msg-9051" },
"message": {
"order": {
"id": "ord-EFI-2026-0811-4471",
"status": "CANCELLED",
"fulfillments": [{
"id": "FUL-1",
"state": { "descriptor": { "code": "CANCELLED" } }
}],
"cancellation": {
"cancelled_by": "CONSUMER",
"reason": { "id": "4",
"descriptor": { "short_desc": "Change of plan" } },
"time": "2026-08-11T09:28:02Z"
},
"quote": {
"price": { "currency": "INR", "value": "0.00" },
"breakup": [{ "title": "Cancellation fee",
"price": { "currency": "INR", "value": "0.00" } }]
},
"payments": [{ "id": "PAY-1", "status": "NOT-PAID" }]
}
}
}The quote on a cancelled order is what is actually owed — often zero, sometimes a fee. It replaces the original quote entirely. Billing against the pre-cancellation figure is a straightforward way to overcharge a customer.
Fees follow fulfilment state
The cancellation_terms returned at init bind a fee to a fulfilment state. Which fee applies is decided by the state at the moment of cancellation, not by the clock:
| State when cancelled | Typical fee | Rationale |
|---|---|---|
RESERVED, well before start | Zero | Nothing lost |
RESERVED, close to start | Partial | The connector was held and turned others away |
STARTED | Partial or full | Capacity was committed |
CHARGING | Not cancellable | Use update — energy was delivered |
on_cancel response is a chargeback in the making.BPP-initiated cancellation
on_cancel can arrive unsolicited, and for EV charging this is common:
- The charger developed a fault before the driver arrived.
- The reservation expired without the driver plugging in.
- The site became unavailable — power cut, closure, obstruction.
- Payment authorisation failed on a pre-payment order.
cancelled_by distinguishes these — PROVIDER rather than CONSUMER. The difference matters commercially as well as technically: a provider-initiated cancellation should not attract a consumer fee, and a BAP that applies one because it did not read the field will be refunding it later.
The driver-facing handling matters more than the protocol handling. Someone en route to a charger that has just cancelled needs an alternative offered immediately, not a notification that their booking is gone.
Production lessons
- Fetch the network's cancellation reason list rather than inventing codes.
- Compute and display the fee before cancelling, from the terms stored at init.
- Read
cancelled_by. Never charge a consumer fee on a provider-initiated cancellation. - Bill from the post-cancellation quote, never the original.
- Handle unsolicited
on_cancelas a first-class path, with an immediate alternative offered to the driver. - Make cancel idempotent. Cancelling twice should return the same cancelled order, not an error.
- Refuse to cancel once charging has begun and route the request to update instead.
Frequently asked questions
It voids an order before the service is delivered, quoting a network-defined cancellation reason ID. The connector is released, any hold is lifted, and a fee may apply based on the cancellation terms agreed at init.
From the cancellation_terms returned at init, which bind a fee to a fulfilment state. The fee that applies is decided by the state at the moment of cancellation — typically zero while merely reserved, partial closer to the start time, and not cancellable at all once charging has begun.
Yes, and in EV charging it is common — a charger faults, a reservation expires, a site loses power, or payment authorisation fails. These arrive as unsolicited on_cancel messages with cancelled_by set to PROVIDER, and no consumer cancellation fee should be applied.
No. Once energy has been delivered the order must be completed and billed for what was consumed, using the update action. Cancelling leaves the provider with an unpaid charge and no clean way to bill it.