OCPP MESSAGE · UPDATED 11 AUG 2026

StartTransaction: opening a session

This is the message that turns an authorised driver into a billable session. Everything financial that follows — the meter readings, the stop record, the CDR, the invoice — hangs off the transaction ID this message creates.

PART OF THE OCPP COMPLETE GUIDE · 14 MESSAGE GUIDES

IN ONE PARAGRAPH

The charger reports which connector, which credential and the meter reading at the moment power starts; the CSMS assigns a transaction ID that identifies the session forever after. The hard part is offline behaviour: a charger with no connection must still start transactions, so it invents temporary IDs and reconciles later.

The message

// Charge point -> CSMS
[2, "19223204", "StartTransaction", {
  "connectorId": 1,
  "idTag": "DR88231ABCD",
  "meterStart": 4471820,
  "timestamp": "2026-08-11T09:12:00Z",
  "reservationId": 8823
}]

// CSMS -> charge point
[3, "19223204", {
  "transactionId": 770142,
  "idTagInfo": { "status": "Accepted" }
}]
FieldNotes
connectorIdNever 0 here — a transaction belongs to a physical connector
idTagThe credential; may differ from the one used to stop, if they share a parentIdTag
meterStartWatt-hours, not kWh. Cumulative register reading, not zero.
timestampFrom the charger's clock — see Heartbeat
reservationIdPresent only if this session claims a reservation
transactionIdAssigned by the CSMS; the identity for everything downstream
meterStart is a cumulative register in watt-hours. It is the odometer, not the trip counter. Energy delivered is meterStop minus meterStart, and treating either as a per-session value produces bills in the thousands of kWh. Dividing by 1000 in the wrong place is the other half of this bug.

The idTagInfo can still refuse

The response carries an idTagInfo even though the driver was usually authorised moments earlier by Authorize. This is not redundant — it is the CSMS's last chance to stop a session, and it fires in real cases: a token blocked in the seconds between authorisation and start, a ConcurrentTx the charger could not know about, an offline-authorised session the CSMS now rejects.

Critically, the transaction still exists. The CSMS assigned an ID. A charger receiving a non-Accepted status stops the session it just started, and that produces a StopTransaction with reason DeAuthorized. Your platform has to handle a transaction that opens and closes within seconds having delivered almost no energy.

Offline transactions

A charger that cannot reach the CSMS still has a driver in front of it. Assuming the offline authorisation policy permits it, the charger starts the session anyway — which means it needs a transaction ID before the CSMS can give it one.

The convention is a locally generated temporary ID, commonly negative, replaced once the queued StartTransaction is delivered and the real ID comes back.

Offline:  charger assigns  transactionId = -3312
          MeterValues and StopTransaction reference -3312

Reconnect: StartTransaction replayed → CSMS assigns 770143
           charger remaps -3312 → 770143 in queued messages

What this means for the platform:

  • Expect StartTransaction messages with timestamps hours old. Trust the message timestamp, not receipt time.
  • Expect out-of-order arrival. A queued StopTransaction can arrive before its StartTransaction if the charger flushes its queue oddly.
  • Expect duplicates. A charger unsure whether delivery succeeded will resend.
  • Never reject on timestamp age. A day-old transaction is real revenue.

Idempotency here is not optional. Key on the charger identity plus connector plus meterStart plus timestamp, and de-duplicate before creating a billable record.

From transaction to OCPI Session

On a CPO platform this message is what creates the OCPI Session pushed to roaming partners.

OCPPOCPI Session
transactionIdInternal join key behind session_id
timestampstart_date_time
idTagcdr_token.uid
connectorIdconnector_id, plus the EVSE it belongs to
meterStartBaseline for kwh — never published directly

Where a remote start came in through OCPI START_SESSION, the authorization_reference from that command must be carried onto the Session and the eventual CDR. That is the only clean thread from an eMSP's original request to the invoice, and it has to be stitched here — at the moment the transaction is created — because nothing later has both pieces.

Production lessons

  • Treat meterStart as watt-hours from a cumulative register. Unit and baseline errors here are the most expensive arithmetic bugs in EV charging.
  • Handle negative and temporary transaction IDs. They are normal, not corrupt data.
  • Make ingestion idempotent before anything becomes billable.
  • Trust the message timestamp over receipt time for anything billing-related.
  • Handle immediate DeAuthorized stops — zero-energy transactions that must not produce an invoice.
  • Stitch the OCPI correlation reference at creation time. It cannot be recovered later.
  • Alert on StartTransaction without a matching StopTransaction beyond a plausible session length — that is either a stuck session or a lost message, and both cost money.

Frequently asked questions

What does OCPP StartTransaction do?

The charge point reports the connector, credential, meter reading and timestamp at the moment charging begins, and the CSMS responds with a transactionId that identifies the session for every subsequent message, including MeterValues and StopTransaction.

Is meterStart the energy used in this session?

No. It is a cumulative register reading in watt-hours — an odometer, not a trip counter. Energy delivered is meterStop minus meterStart. Treating it as a per-session value produces bills in the thousands of kWh.

How do OCPP transactions work when the charger is offline?

The charger generates a temporary local transaction ID, commonly negative, and queues the messages. When it reconnects it replays StartTransaction, receives a real ID from the CSMS, and remaps the queued messages. Platforms must therefore expect old timestamps, out-of-order arrival and duplicates.

Can the CSMS refuse a transaction in the StartTransaction response?

Yes. The idTagInfo can return a non-Accepted status if the token was blocked in the intervening seconds or a concurrent transaction exists. The transaction still exists and has an ID, so the charger stops it and sends a StopTransaction with reason DeAuthorized.