Dry-run a network import into a migration, or apply it
The project's network import (POST /v1/tenants/{tenant_id}/imports: the same bodies, limits, plan, apply and resume) into the migration's project, for the migration's teams. Once applied, every station the import names (created, updated or already identical) joins the migration's chargers in the state imported, with the routing key <project>/<charger_id> (or the global connection name where per-project charger URLs are off): its proxy's allowlist names the charger so. Each row then carries migration_state and charger_key. A station already in another migration stays out (its migration_state is null). Audited as network_import.dry_run and network_import.applied, and migration.charger.added in the same transaction as the addition (503 migration_audit_unavailable when it cannot be stored: apply again with the same Idempotency-Key; it answers 200, adds the stations and records network_import.applied, and the core writes are not repeated). Needs migration:import over every site: the client role (the project team's owners and admins), Ivora support or a partner (an invited partner team's owners, admins, developers and operators); a participant narrowed to some sites cannot import. A personal or staff key bound to the project needs stations:write, a team migration key migration:import; project keys and app tokens get 404. Only the dry run's maker applies it: the same key, or a signed-in member of the same participant team (Ivora support for its own; 403 forbidden otherwise). A key makes at most 10 dry runs and applies a minute (429 rate_limited with Retry-After). A migration that is paused, completed or archived refuses dry runs and applies (409 migration_closed). Errors: 402 billing_suspended, 402 payment_method_required, 404 import_not_found, 404 migration_not_found, 409 global_charger_url_retired, 409 import_applied, 409 import_in_progress, 409 import_reverted, 409 import_stale, 409 migration_closed, 409 request_in_progress, 409 self_serve_charger_cap, 413 request_too_large, 415 unsupported_media_type, 422 feed_failed, 422 feed_invalid, 422 feed_refused, 422 feed_too_large, 422 import_too_large, 503 migration_audit_unavailable, 503 outcome_unknown. See Errors and statuses.
Path parameters
- migration_idstringRequiredPattern
^mig_[0-9a-f]{32}$
Query parameters
- applybooleanApply the dry run named by dry_run_idDefault
false - dry_run_idstring | nullThe dry run to apply (its id), one of this migration'sPattern
^imp_[0-9a-f]{32}$
Headers
- idempotency-keystring | nullRequired with apply=true
Request body (optional)
- sourcestringRequired
- documentobject | array of any | nullAn OCPI 2.2.1 Locations response ({"data": [...]}), a list of Location objects or one Location
- feedany | null
- charger_mapobject | nullEVSE uid to the charger it belongs to: "CP001" or {"charger_id": "CP001", "evse_number": 2, "ocpp_version": "1.6"}. Without an entry an EVSE is its own charger, with its uid as charger_id
Returns · 200
- idstringRequired
- tenant_idintegerRequired
- migration_idstring | nullThe migration this import belongs to (made under /v1/migrations/{migration_id}/imports): its applied stations join that migration as imported. null for a project import.
- sourceenumRequiredOne of
csv,ocpi_locations - originstring | nullRequiredThe fetched feed's host and path (no query string or token); null for an upload
- statusenumRequiredOne of
planned,applying,applied,partial,reverted,partially_reverted - identityenumRequiredproject: chargers keep their own IDs under the project's charger URL; global: each charger ID is a globally unique OCPP connection nameOne of
project,global - countsImportCountsRequired
Child attributes
- createintegerRequired
- updateintegerRequired
- skipintegerRequired
- errorintegerRequired
- totalsImportTotalsRequired
Child attributes
- locationsintegerRequiredLocations in the source
- stationsintegerRequiredChargers in the source, each one station
- evsesintegerRequired
- connectorsintegerRequired
- actorstringRequired
- created_atstringRequired
- updated_atstringRequired
- applied_atstring | nullRequired
- reverted_atstring | nullRequired
- rowsarray of ImportRowRequired
Child attributes
- itemstring | nullRequiredThe row's ID in this import (L<n> for a location, S<n> for a station); null for a source row that could not be read
- kindenumRequiredOne of
location,station,row - actionenumRequiredWhat apply does: create, update (change the existing resource), skip (identical, or removed in the source) or error (nothing is written for it)One of
create,update,skip,error - stateenumRequiredplanned in a dry run; after apply pending, done, failed or skipped; after a revert reverted or keptOne of
planned,pending,done,failed,skipped,reverted,kept - sourcestring | nullRequiredWhere the row comes from: CSV line numbers, or the position in the OCPI document
- refstring | nullA location's reference: the CSV location_ref or the OCPI Location id, stored as its external_reference
- charger_idstring | null
- namestring | nullThe station's OCPP connection name in Ivora
- location_refstring | null
- location_idinteger | null
- station_idinteger | null
- connector_idsarray of integer | nullThe station's connector resource IDs, once applied
- evsesinteger | null
- connectorsinteger | null
- changesarray of stringThe fields an update changes
- codestring | null
- messagestring | null
- warningsarray of string
- migration_stateenum | nullA migration's import (migration_id): the station's state on the migration's board once it joined (imported first); null while it is not in this migration (not applied yet, or in another migration). null on a project import.One of
imported,proxied,shadow,parity_checked,moved,rolling_back,rolled_back - charger_keystring | nullA migration's import: the charger proxy's routing key the station joined with, <project>/<charger id> (or the global connection name); null while not in the migration.
- follow_upsarray of stringRequiredSteps outside this import: RFID tokens, tariffs, EVSE IDs for roaming, credentials
curl --fail-with-body -X POST "https://api.ivoracharge.com/v1/migrations/mig_0123456789abcdef0123456789abcdef/imports" \
-H "Authorization: Bearer $IVORA_API_KEY" \
-H "Idempotency-Key: order-2026-09-30-0001" \
-H "Content-Type: application/json" \
-d '{
"source": "ocpi_locations"
}'{
"id": "id_0123456789abcdef",
"tenant_id": 1042,
"migration_id": "migration_0123456789abcdef",
"source": "csv",
"origin": "string",
"status": "planned",
"identity": "project",
"counts": {
"create": 1,
"update": 1,
"skip": 1,
"error": 1
},
"totals": {
"locations": 1,
"stations": 1,
"evses": 1,
"connectors": 1
},
"actor": "string",
"created_at": "2026-09-30T17:00:00Z",
"updated_at": "2026-09-30T17:00:00Z",
"applied_at": "2026-09-30T17:00:00Z",
"reverted_at": "2026-09-30T17:00:00Z",
"rows": [
{
"item": "string",
"kind": "location",
"action": "create",
"state": "planned",
"source": "string",
"ref": "string",
"charger_id": "charger_0123456789abcdef",
"name": "bay-01",
"location_ref": "string",
"location_id": 7,
"station_id": 1,
"connector_ids": [
1
],
"evses": 1,
"connectors": 1,
"changes": [
"string"
],
"code": "string",
"message": "string",
"warnings": [
"string"
],
"migration_state": "imported",
"charger_key": "string"
}
],
"follow_ups": [
"string"
]
}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.



