The Arcora operator API
The HTTPS API your backend serves so your chargers work in the Arcora app. Your backend talks OCPP to the chargers; the app only ever talks to this API.
Basics
- Transport
- HTTPS, JSON (UTF-8). All paths go under your backend URL + /v1.
- Auth
- Every request carries
Authorization: Bearer <token>, the driver's Arcora session token. - Times
- ISO 8601 UTC, e.g. 2026-10-21T16:12:00Z
- Money
- Decimals in your currency (USD for now), rounded to the cent
- Energy, power
- kWh and kW, as decimals
Verifying the driver
The token is a signed JWT from Arcora's sign-in provider (Clerk). Verify its signature against Arcora's public keys (JWKS) and check exp and nbf. Reject a missing or invalid token with HTTP 401.
sub is the driver's stable user ID. Scope every session and receipt to it, and never trust a user ID sent in a request body. Another driver's session is a 404, not a 403.
Endpoints
| Method | Path | Returns | Notes |
|---|---|---|---|
| GET | /chargers?lat=&lng=&radiusKm= | Charger[] | Nearest first; radiusKm defaults to 25 |
| GET | /chargers?q= | Charger[] | Text match on name and address |
| GET | /chargers/{id} | Charger | |
| GET | /chargers/by-code/{code} | Charger | The code printed on the unit and in its QR link |
| POST | /chargers/{id}/notify | 204 | Notify the driver when a port frees up |
| POST | /sessions | 201 Session | Remote start on a free port |
| GET | /sessions/active | Session or 204 | The driver’s live session with you, if any |
| GET | /sessions/{id} | Session | Polled every 2 s while the session screen is open |
| POST | /sessions/{id}/stop | Session | Remote stop; returns Finishing right away |
| GET | /sessions/{id}/receipt | Receipt | 404 until the session is Complete |
| GET | /receipts | Receipt[] | The driver’s past sessions, newest first |
Errors
{ "error": { "code", "message" } }. The app shows a designed screen for each code below; anything else should be a 5xx, which the app treats as a network problem and offers a retry.| Code | HTTP | When |
|---|---|---|
NOT_FOUND | 404 | Unknown charger, code or session, or one that belongs to another driver |
CHARGER_UNAVAILABLE | 409 | No free port, charger offline or faulted, or it rejected the remote start |
SESSION_ALREADY_ACTIVE | 409 | The driver already has a live session with you |
PAYMENT_FAILED | 402 | You refused the start for a payment reason |
From OCPP to the API
| Field | OCPP 1.6J | OCPP 2.0.1 |
|---|---|---|
kwhDelivered | Energy.Active.Import.Register now minus at start | Same register in TransactionEvent |
chargingSpeedKw | Power.Active.Import (0 unless charging) | Same, in meterValue |
socPercent | SoC measurand, if the charger sends it | Same |
stopReason | StopTransaction reason | transactionInfo.stoppedReason |
Port status | StatusNotification status | StatusNotification connectorStatus |
Starting a session is an OCPP remote start (RemoteStartTransaction in 1.6, RequestStartTransaction in 2.0.1), and stopping is the matching remote stop. Price and cost are yours to compute: OCPP carries no price.
The connection check
- 1Finds your test charger by its code, then by ID
- 2Lists chargers near it, and searches by name
- 3Sends no token, then a forged token, and expects HTTP 401 both times
- 4Asks for an unknown charger and expects a NOT_FOUND error
- 5Reads the driver’s active session and receipts
Need an OCPP server to build on? See backend options. The protocol itself is published by the Open Charge Alliance.