Chargers
Register the account's charger against a MID-certified model from the Joulo catalog.
Chargers
ERE requires MID-metered kWh. Registering the account's charger against a MID-certified model from the Joulo catalog is what makes the account eligible: the catalog carries the verified MID verdict, so you don't assert MID status yourself.
Register a charger
POST /v1/chargers — scope cpo:chargers:write
curl -X POST https://api.joulo.nl/functions/v1/api/v1/chargers \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"account_id": "60092124-c768-4191-9c9d-55ef3fc49999",
"catalog_charger_id": "81978554-c5ec-4215-8968-95d34a4e8c68",
"serial_number": "ACE0013982"
}'{
"ok": true,
"charger_id": "…",
"catalog": { "brand": "Alfen", "model": "Eve Double Plus" },
"mid_eligible": true,
"account_ere_eligible": true
}Body
| Field | Required | Description |
|---|---|---|
account_id | yes | The account to register the charger on. |
catalog_charger_id | one of the two | Id of a MID model in the Joulo catalog. |
ocpp_vendor + ocpp_model | one of the two | The chargePointVendor and chargePointModel from the unit's BootNotification. Joulo resolves the catalog model server-side. Ignored when you send catalog_charger_id. |
serial_number | first charger: no • additional chargers: yes | The unit's serial/meter number. Doubles as the idempotency key from the second charger on. |
{
"account_id": "60092124-c768-4191-9c9d-55ef3fc49999",
"ocpp_vendor": "eNovates",
"ocpp_model": "0A000T2N0031231",
"serial_number": "ACE0013982"
}The response echoes catalog.catalog_charger_id, so you can cache what the
pair resolved to. A pair we cannot place returns 422 catalog_unresolved.
Catalog ids. Resolve them from the BootNotification pair, or look them up
with the catalog endpoint below. The model must be MID-certified in the
catalog; a non-MID model returns 422 catalog_not_mid. If your model is
missing, send Joulo the MID evidence (EU Declaration of Conformity or
datasheet showing the built-in MID meter) and we add it.
Catalog ids are per environment. The sandbox and production hold separate
databases, so the same model has a different catalog_charger_id in each.
Resolve or look up the id in the environment you are calling. Never hardcode
one you saw on the sandbox.
Resolve from a BootNotification
GET /v1/catalog/chargers/resolve — any valid CPO token, no specific scope
Pass ?vendor= and ?model= exactly as the charger reported them in its
BootNotification. Most brands put a nameplate code in chargePointModel, not
the marketing name, so a literal comparison against brand + model never
matches. This endpoint runs the same resolver Joulo's own OCPP gateway uses:
per-model alias lists, including prefix patterns for SKU families.
curl -G "https://api.joulo.nl/functions/v1/api/v1/catalog/chargers/resolve" \
--data-urlencode "vendor=eNovates" \
--data-urlencode "model=0A000T2N0031231" \
-H "Authorization: Bearer <token>"{
"resolved": true,
"vendor": "eNovates",
"model": "0A000T2N0031231",
"catalog_charger_id": "793683e1-b185-4c58-96a0-3b1da599ec8e",
"brand": "Enovates",
"catalog_model": "One",
"mid_meter": true
}A pair we cannot place is a normal 200 with "resolved": false, plus the
brand's MID models as suggestions:
{
"resolved": false,
"vendor": "Acme",
"model": "AC-9000-XYZ",
"detail": "No catalog model matches this vendor + model. Send Joulo the pair and we add the alias.",
"suggestions": []
}Send us the pair and we add the alias, so the next unit of that family resolves for every CPO at once. Do not build your own vendor + model mapping table: it drifts from ours the moment a manufacturer ships a new SKU suffix.
mid_meter. A resolved model is not automatically a MID model. Check
this field before you register the charger, or POST /v1/chargers answers
422 catalog_not_mid.
Find the catalog id
GET /v1/catalog/chargers — any valid CPO token, no specific scope
Lists the MID-certified models in the Joulo catalog. Filter with
?search= (matches brand and model, case-insensitive) and page with
?limit (default 100, max 200).
curl "https://api.joulo.nl/functions/v1/api/v1/catalog/chargers?search=alfen" \
-H "Authorization: Bearer <token>"{
"models": [
{
"catalog_charger_id": "81978554-c5ec-4215-8968-95d34a4e8c68",
"brand": "Alfen",
"model": "Eve Double Plus"
}
],
"count": 1
}Multiple chargers, serial-based idempotency. An account can carry up to
10 active chargers (they share the account's connection; monthly kWh sums
across them). Re-posting a serial_number we already have returns the
existing charger ("idempotent": true) instead of creating a duplicate.
Once an account has a charger, serial_number is required for every next
registration (409 serial_required) — otherwise a retry and an intentional
second charger would be indistinguishable.
account_ere_eligible. Registering the MID charger is usually the last
automated gate. When the response returns account_ere_eligible: true, the
account has cleared every requirement — validated EAN, signed machtiging, MID
charger, and IBAN — and its kWh will count toward ERE. If it's false, one of
those is still missing.
Errors
| HTTP | error |
|---|---|
| 400 | invalid_account_id, invalid_catalog_charger_id, vendor_and_model_required |
| 404 | account_not_found, catalog_not_found |
| 409 | no_connection (register the account's connection first), serial_required |
| 422 | catalog_not_mid, catalog_unresolved, charger_limit |