Log inTalk to us

Run a parity report: compare chargers with the previous platform

post/v1/migrations/{migration_id}/parity/reports
Requires an API key

For each charger in scope (station_ids, location_ids or all: true; 500 at most), compares its baseline with Ivora's records: configuration (the keys of the baseline against the configuration Ivora recorded; keys that decide where the charger connects and secrets are skipped; on OCPP 2.x the Actual attribute only, and a label with different values on several EVSEs is skipped as ambiguous), tariff (the price of each connector, as Ivora would bill it; a complex tariff, with elements, rules or a time zone, is not checked: complex_tariff) and sessions (count and energy of the sessions that started in the baseline's window, within tolerances; without baseline sessions, an OCPP 1.6 charger in shadow mode is compared with the sessions the charger proxy recorded from the control link, in since..until). A charger passes when no section fails and every section in require passed, else it failed or is incomplete. A charger on the previous platform whose latest report passed is parity_checked on the board until it moves. Read-only for chargers: nothing is sent to a charger and nothing in Ivora's records of it changes. Needs migration:plan (client, support, partner; a key needs stations:write). A participant narrowed to some sites covers and reads the chargers at its sites only. A retry with the same Idempotency-Key returns the same report. Audited (migration.parity.checked) in the same transaction; nothing is stored unless its entry is. Errors: 404 migration_charger_not_in_migration, 404 migration_not_found, 409 migration_closed, 503 migration_audit_unavailable. See Errors and statuses.

Path parameters

  • migration_idstringRequired
    Pattern ^mig_[0-9a-f]{32}$

Headers

  • idempotency-keystringRequired

Request body

  • station_idsarray of integer | null
    Check these chargers.
  • location_idsarray of integer | null
    Or every migration charger at these sites.
  • allboolean | null
    Or true: every charger of the migration (500 at most).
  • sincestring | null
    Session window for chargers whose baseline has no sessions (the OCPP 1.6 shadow-mode ledger is compared instead): ISO 8601 with offset; default 7 days before until.
    Up to 40 characters
  • untilstring | null
    Its end, exclusive; default now. At most 31 days after since.
    Up to 40 characters
  • tolerancesParityTolerances
    Child attributes
    • session_countinteger
      Sessions the two counts may differ by.
      Default 0 · Minimum 0 · Maximum 1000
    • energy_whinteger
      Wh the two energy totals may always differ by.
      Default 100 · Minimum 0 · Maximum 1000000000
    • energy_rationumber
      Or this share of the previous platform's total, when larger.
      Default 0.01 · Minimum 0 · Maximum 1
  • ignore_keysarray of string
    Configuration keys not compared, such as keys Ivora sets on purpose (HeartbeatInterval).
  • requirearray of enum
    The sections a charger must pass to pass. A section left out still fails the charger when it was compared and differs.

Returns · 201

  • idstringRequired
    mpr_...
  • migration_idstringRequired
  • scopeParityScopeRequired
    Child attributes
    • station_idsarray of integer | null
    • location_idsarray of integer | null
    • allboolean | null
  • sincestringRequired
    The session window for chargers compared with the shadow-mode ledger.
  • untilstringRequired
  • tolerancesobjectRequired
  • ignore_keysarray of stringRequired
  • requirearray of enumRequired
  • countsobjectRequired
    Chargers passed, failed, incomplete, and total (of the caller's sites when narrowed).
  • created_bystringRequired
  • created_atstringRequired
  • chargersarray of ParityResult | nullRequired
    Each charger's result, ordered by charger_key; null in the list.
    Child attributes
    • station_idintegerRequired
    • charger_keystringRequired
    • location_idinteger | nullRequired
    • statusenumRequired
      passed: every required section passed and none failed; failed: a section differs beyond its tolerance; incomplete: a required section could not be checked.
      One of passed, failed, incomplete
    • sectionsParitySectionsRequired
      Child attributes
      • configurationConfigurationParityRequired
        Child attributes
        • statusenumRequired
          One of passed, failed, not_checked
        • reasonstring | nullRequired
          Why it was not checked: no_baseline, not_recorded (Ivora has not read the charger's configuration yet), nothing_compared, too_many_items (Ivora recorded more than 2,000 items for the charger), protocol_unsupported.
        • comparedintegerRequired
          Keys compared.
        • skippedarray of stringRequired
          Keys not compared: ignored, secret, deciding where the charger connects (its URL and identity differ on purpose), or ambiguous.
        • ambiguousarray of string
          OCPP 2.x labels skipped because Ivora recorded them with different values on more than one EVSE or attribute. Only the Actual attribute is compared.
        • differencesarray of ConfigurationDifferenceRequired
          Child attributes
          • keystringRequired
          • kindenumRequired
            different: both have it with other values; missing: Ivora has not recorded it.
            One of different, missing
          • previousstringRequired
          • ivorastring | nullRequired
      • tariffTariffParityRequired
        Child attributes
        • statusenumRequired
          One of passed, failed, not_checked
        • reasonstring | nullRequired
          Why it was not checked: no_baseline, no_connectors, complex_tariff (Ivora bills a connector by a tariff with elements, rules or a time zone, so its base prices are not what it charges; a missing tariff or another currency still fails).
        • previousobject | nullRequired
          The baseline's tariff.
        • connectorsarray of TariffConnectorRequired
          Ivora's price on each connector.
          Child attributes
          • connector_idintegerRequired
          • tariff_idinteger | nullRequired
          • sourceenumRequired
            Where Ivora's tariff comes from: the connector's own, its location's default, the project's default, or none.
            One of connector, location, project, none
          • currencystring | nullRequired
          • rate_minor_per_kwhinteger | number | nullRequired
            Minor units; a decimal number for a sub-cent price.
          • rate_minor_per_minuteinteger | number | nullRequired
          • session_fee_minorinteger | number | nullRequired
        • differencesarray of TariffDifferenceRequired
          Child attributes
          • connector_idintegerRequired
          • fieldenumRequired
            tariff: Ivora prices the connector with no tariff (or one it cannot read).
            One of tariff, currency, rate_minor_per_kwh, rate_minor_per_minute, session_fee_minor
          • previousstring | integer | number | nullRequired
          • ivorastring | integer | number | nullRequired
      • sessionsSessionsParityRequired
        Child attributes
        • statusenumRequired
          One of passed, failed, not_checked
        • reasonstring | nullRequired
          Why it was not checked: no_baseline (no sessions in the baseline and no shadow-mode ledger entries in the window), too_many_sessions.
        • sourceenum | nullRequired
          baseline: the totals recorded from the previous platform; shadow_ledger: the sessions the charger proxy recorded from the control link in shadow mode (OCPP 1.6).
          One of baseline, shadow_ledger
        • sincestring | nullRequired
        • untilstring | nullRequired
        • previousobject | nullRequired
          Child attributes
          • countintegerRequired
          • energy_whintegerRequired
        • ivoraobject | nullRequired
          Ivora's sessions on the charger that started in the window (in shadow mode, its copy).
          Child attributes
          • countintegerRequired
          • energy_whintegerRequired
        • differencesarray of SessionDifferenceRequired
          Child attributes
          • fieldenumRequired
            One of count, energy_wh
          • previousintegerRequired
          • ivoraintegerRequired
          • toleranceintegerRequired
    • checked_atstringRequired
POST /v1/migrations/{migration_id}/parity/reports
curl --fail-with-body -X POST "https://api.ivoracharge.com/v1/migrations/mig_0123456789abcdef0123456789abcdef/parity/reports" \
  -H "Authorization: Bearer $IVORA_API_KEY" \
  -H "Idempotency-Key: order-2026-09-30-0001" \
  -H "Content-Type: application/json" \
  -d '{}'
Response · 201JSON
{
  "id": "id_0123456789abcdef",
  "migration_id": "migration_0123456789abcdef",
  "scope": {
    "station_ids": [
      1
    ],
    "location_ids": [
      7
    ],
    "all": false
  },
  "since": "string",
  "until": "string",
  "tolerances": {},
  "ignore_keys": [
    "string"
  ],
  "require": [
    "configuration"
  ],
  "counts": {},
  "created_by": "string",
  "created_at": "2026-09-30T17:00:00Z",
  "chargers": [
    {
      "station_id": 1,
      "charger_key": "string",
      "location_id": 7,
      "status": "passed",
      "sections": {
        "configuration": {
          "status": "passed",
          "reason": "string",
          "compared": 1,
          "skipped": [
            null
          ],
          "ambiguous": [
            null
          ],
          "differences": [
            null
          ]
        },
        "tariff": {
          "status": "passed",
          "reason": "string",
          "previous": {},
          "connectors": [
            null
          ],
          "differences": [
            null
          ]
        },
        "sessions": {
          "status": "passed",
          "reason": "string",
          "source": "baseline",
          "since": "string",
          "until": "string",
          "previous": {
            "count": null,
            "energy_wh": null
          },
          "ivora": {
            "count": null,
            "energy_wh": null
          },
          "differences": [
            null
          ]
        }
      },
      "checked_at": "2026-09-30T17:00:00Z"
    }
  ]
}
Requires an approved production API keyProduction access starts with a request, a short meeting with Ivora and a card on file, after which Ivora staff grant your account access. How to request access
Try itproduction · api.ivoracharge.com

Paste a production api key (iv_live_…). Create keys in Developer tools. The key stays in this page's memory, is sent only to https://api.ivoracharge.com and clears when you reload. Test keys are refused.

POST is a write: you confirm the method, path and project before it is sent, with a generated Idempotency-Key.