BECKN ACTION · UPDATED 11 AUG 2026

confirm: creating the order

confirm is the commitment. Everything before it was negotiation; after it there is an order with an ID, a state, and usually a token that will unlock a charger. It is also the one action in the chain where a duplicate is genuinely expensive.

PART OF THE BECKN FOR EV CHARGING GUIDE · 10 ACTION & CONCEPT GUIDES

IN ONE PARAGRAPH

confirm turns the draft order into a real one. The on_confirm response carries an order ID, a fulfilment state, and for EV charging an authorization token the driver presents at the charge point. Because a retry can create a second order, idempotency on transaction_id is not optional here.

What confirm commits to

Up to this point nothing exists on the BPP's side but a conversation. confirm creates a durable order: the provider allocates capacity, the payment obligation becomes real, and the cancellation terms agreed at init start to apply.

The BAP sends back the order it received from on_init, unchanged apart from payment status. Modifying the order at this point — a different item, a different quantity — is not a confirm; it is a new transaction.

The exchange

POST https://cpo.electreefi.in/beckn/confirm

{
  "context": {
    "domain": "ev-charging:uei", "action": "confirm", "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-9024",
    "timestamp": "2026-08-11T09:00:44Z", "ttl": "PT30S"
  },
  "message": {
    "order": {
      "provider": { "id": "EFI" },
      "items": [{ "id": "EVSE-014-02",
        "quantity": { "selected": { "measure": { "value": "25", "unit": "kWh" } } } }],
      "billing": { "name": "Example Mobility Services",
                   "email": "billing@emsp.example.com" },
      "fulfillments": [{ "id": "FUL-1",
        "customer": { "contact": { "phone": "+919136075015" } } }],
      "payments": [{ "id": "PAY-1", "type": "POST-FULFILLMENT",
                     "status": "NOT-PAID", "collected_by": "BAP" }]
    }
  }
}

And the response that matters:

POST https://emsp.example.com/beckn/on_confirm

{
  "context": { "...": "same transaction_id", "action": "on_confirm",
               "message_id": "msg-9024" },
  "message": {
    "order": {
      "id": "ord-EFI-2026-0811-4471",
      "status": "ACTIVE",
      "provider": { "id": "EFI" },
      "items": [{ "id": "EVSE-014-02" }],
      "quote": { "price": { "currency": "INR", "value": "535.93" } },
      "fulfillments": [{
        "id": "FUL-1",
        "state": { "descriptor": { "code": "RESERVED" } },
        "authorization": {
          "type": "OTP",
          "token": "884213",
          "valid_from": "2026-08-11T09:05:00Z",
          "valid_to":   "2026-08-11T09:35:00Z"
        },
        "stops": [{ "type": "START",
                    "location": { "gps": "28.6270,77.3721" },
                    "instructions": { "name": "Bay A2" } }]
      }],
      "created_at": "2026-08-11T09:00:45Z"
    }
  }
}

The authorization object

This is where a Beckn order becomes a physical action. The authorization block is what the driver presents at the charge point to begin charging.

FieldMeaning
typeHow it is presented — OTP, QR or similar
tokenThe value itself
valid_fromNot usable before this
valid_toExpires here — the reservation window
valid_to is a reservation expiry in disguise. The BPP is holding a connector until then, and it stops holding it afterwards. Show the driver a countdown, and if their arrival slips, cancel and re-book rather than letting the window lapse silently — the same discipline as an OCPI RESERVE_NOW expiry.

On the BPP side, this token is what links the Beckn order to the charging session underneath. When the driver enters it, the CPO starts a session and can now correlate that session — and the CDR that follows — back to transaction_id. Without that link, reconciling Beckn orders against charging records becomes guesswork.

Idempotency is mandatory here

Every other action in the chain is safe to retry. confirm is not: a duplicate creates a second order, a second reservation, and eventually a second charge.

Retries are unavoidable — a timeout, a dropped callback, an impatient driver tapping twice. The BPP has to absorb them:

  • Key idempotency on transaction_id. A second confirm for a transaction that already has an order returns the existing order, not a new one.
  • Return the same on_confirm payload for a repeat, including the same order ID and the same authorization token.
  • On the BAP side, disable the button the moment confirm is sent, and keep it disabled until a callback or the TTL expires.

A BPP without confirm idempotency will produce duplicate orders in production. It is not a question of whether the retry happens.

When confirm fails

SituationCorrect handling
EVSE taken between init and confirmNACK or an on_confirm with an unavailable fulfilment state — offer alternatives from the original search
Payment authorisation declinedFail before creating the order; do not create then cancel
Callback never arrivesQuery with status on transaction_id before retrying — the order may exist
Duplicate confirm receivedReturn the existing order

The third row is the one that catches teams out. A missing callback does not mean a missing order. Retrying blind is how duplicates get created even when the BPP is behaving correctly.

Production lessons

  • Idempotency on transaction_id, without exception. The single most important rule in this action.
  • Never retry confirm without checking status first. Silence is not failure.
  • Persist the order ID and authorization token immediately on receipt. Losing the token strands a driver holding a phone at a working charger.
  • Surface valid_to prominently and treat it as a live countdown.
  • Store the confirmed order verbatim. It is the contract, and it is what a dispute is judged against.
  • Link the order to the charging session as soon as the token is used — without that join, Beckn orders and CDRs never reconcile.

Frequently asked questions

What does the Beckn confirm action do?

It commits the draft order, creating a durable order on the BPP's side with an ID and a fulfilment state. The BPP allocates capacity, the payment obligation becomes real, and the cancellation terms agreed at init begin to apply.

What is the authorization token in on_confirm?

For EV charging it is what the driver presents at the charge point to begin charging — typically an OTP or QR code, with valid_from and valid_to bounds. The valid_to timestamp is effectively a reservation expiry, since the BPP stops holding the connector after it.

Why does Beckn confirm need idempotency?

Because a retry can create a second order, a second reservation and eventually a second charge. Retries are unavoidable from timeouts, dropped callbacks and repeated taps, so the BPP must key idempotency on transaction_id and return the existing order for a duplicate.

What should you do if the on_confirm callback never arrives?

Query with the status action on the same transaction_id before retrying. A missing callback does not mean a missing order — the order may already exist, and retrying blind is how duplicates are created.