The message
// Charge point -> CSMS
[2, "19223203", "Authorize", { "idTag": "DR88231ABCD" }]
// CSMS -> charge point
[3, "19223203", {
"idTagInfo": {
"status": "Accepted",
"expiryDate": "2026-12-31T23:59:59Z",
"parentIdTag": "FLEET-HYUNDAI-01"
}
}]parentIdTag groups tokens that share an authorisation identity — a fleet's cards, or a driver's card plus their app credential. It is what lets a session started with one credential be stopped with another, which matters when a driver taps a card to start and then uses the app to stop.
The five verdicts
| Status | Means | Charger does |
|---|---|---|
Accepted | Allowed | Proceeds to StartTransaction |
Blocked | Token is blocked | Refuses; display “card blocked” |
Expired | Past its validity date | Refuses; display “card expired” |
Invalid | Unknown token | Refuses; display “card not recognised” |
ConcurrentTx | Already in a transaction elsewhere | Refuses; display “already charging” |
ConcurrentTx is the one worth designing around deliberately. It exists to stop one credential running several sessions at once, which is both a fraud control and a way to catch a session that never closed. If drivers legitimately need two vehicles charging on one account, that is a business decision to relax it — but the default protects you from a stuck session silently authorising every future tap.
Three ways to authorise
A charger has three mechanisms, and the ordering between them is configurable. This is the substance of the message.
| Mechanism | Source | Works offline |
|---|---|---|
| Remote | Authorize call to the CSMS | No |
| Local list | A list pushed by the CSMS via SendLocalList | Yes |
| Cache | Verdicts the charger remembers from previous Authorize calls | Yes |
The local authorization list
An explicit, versioned list the CSMS pushes to the charger. GetLocalListVersion asks what version the charger holds; SendLocalList replaces it entirely or applies a differential update.
It suits known populations — a depot's fleet cards, a workplace's staff. It does not scale to a public network with millions of tokens, and pushing a large list to a charger on a weak cellular link is its own operational problem.
The authorization cache
The charger remembers verdicts it has seen. A driver who charged here yesterday can charge today even if the link is down. It is automatic and requires no fleet management, and it carries the obvious risk: a token blocked centrally stays valid in the cache until it is cleared.
ClearCache exists for exactly that, and revoking a credential means clearing it across every charger the driver might reach.
What happens when the charger is offline
This is the design decision that matters most, and it is a business decision wearing technical clothing.
| Policy | Offline behaviour | Risk you accept |
|---|---|---|
| Reject everything | No charging without connectivity | Stranded drivers, dead sites during an outage |
| Local list only | Known tokens charge | Unknown legitimate drivers refused |
| List + cache | Known and previously seen tokens charge | Revoked tokens work until cache cleared |
| Allow all offline | Anyone charges | Free electricity |
Whatever you choose, the charger must queue the resulting transactions and replay them when it reconnects. Those late StartTransaction and StopTransaction messages are why settlement windows have to tolerate delayed data.
How this chains to OCPI
On a roaming platform, Authorize is rarely answered by the CPO alone. The chain runs:
- Driver taps a card at the charger.
- Charger sends
Authorizeto its CSMS. - The CSMS does not recognise the token as its own — it belongs to a roaming partner.
- The CSMS calls the eMSP through OCPI Tokens real-time authorisation, or checks its synced whitelist.
- The eMSP's verdict maps back into
idTagInfoand returns to the charger.
The driver is standing there for the whole round trip, so the latency budget is tight — under two seconds end to end. The OCPI whitelist field decides whether step 4 happens at all, which is why that field is the single most important lever on authorisation latency across a roaming network.
Production lessons
- Make the offline policy an explicit decision with a documented exposure, not a firmware default.
- Have a working
ClearCachepath. Revocation is meaningless if you cannot clear caches across the fleet. - Keep the latency budget under two seconds including any roaming hop. Cache entitlement rather than querying a slow billing system inline.
- Never log raw
idTagvalues in plaintext. They are credentials and, in most jurisdictions, personal data. - Use
parentIdTagproperly so a session started with one credential can be stopped with another from the same group. - Monitor the reject-reason distribution. A spike in
Invalidat one site usually means a reader fault, not a wave of bad cards. - Keep local lists small and current. Large lists on weak links fail to deliver and leave chargers on stale versions.
Frequently asked questions
An idTagInfo containing a status of Accepted, Blocked, Expired, Invalid or ConcurrentTx, optionally with an expiryDate and a parentIdTag that groups related credentials such as a fleet's cards.
Through a local authorization list pushed by the CSMS, and through an authorization cache of previously seen verdicts. Most production networks allow both, accepting that a recently revoked token may work until caches are cleared, because a site that goes dark during every connectivity outage is a worse outcome.
The local list is explicit and versioned — the CSMS pushes it with SendLocalList and it suits known populations like fleet or workplace cards. The cache is automatic, built from verdicts the charger has already seen, and requires ClearCache to purge revoked tokens.
The credential is already in an active transaction elsewhere. It prevents one token running several sessions at once, which is both a fraud control and a way to catch a session that never closed properly.
If the CSMS does not recognise the token as its own, it consults the owning eMSP through OCPI Tokens — either a synced whitelist or a real-time authorisation call — and maps that verdict back into idTagInfo. The driver is waiting throughout, so the whole chain needs to complete in under about two seconds.