# EV Charging Stations API with Prices and Status: Eco-Movement (`nabeelbaghoor/ev-charging-stations-api`) Actor

Read global EV charging stations with EVSEs, connectors, power, operators, real-time availability, ad hoc and MSP charging prices and CPO tariffs through the Eco-Movement Data API (OCPI 2.2 or 2.1.1). Full lists, changes since a date, or lookups by location, EVSE or pricing ID. Bring your own key.

- **URL**: https://apify.com/nabeelbaghoor/ev-charging-stations-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** Developer tools, Travel, Integrations
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 ev charging locations

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## EV Charging Stations API with Prices and Status: Eco-Movement

Pull EV charging stations, their EVSEs and connectors, real-time availability, charging prices and CPO tariffs out of the Eco-Movement Data API with your own token, as clean rows you can export to CSV, Excel or JSON or feed into your own app.

Eco-Movement collects charge point data from charge point operators (CPOs), eMobility service providers (MSPs) and other sources across Europe, North America and beyond, cleans it, and serves it through an outbound API built on the OCPI protocol (versions 2.2 and 2.1.1). This actor wraps the read only side of that API on api.eco-movement.com: charging locations with every EVSE and connector, real-time EVSE status, ad hoc and MSP charging prices per connector, and the raw OCPI tariffs operators share. Use it to power an EV charging map or route planner, benchmark charging prices by operator and country, track network growth and uptime, or plan new charging sites. Bring your own API key.

BYOK, not live tested: every route, parameter and response field comes from Eco-Movement's own developer documentation at developers.eco-movement.com (the OpenAPI definitions embedded in its reference pages), and every route was probed on 2026-10-27 with an invalid token. The actor has not been run against a live Eco-Movement token.

### What it does

- **Charging locations**: GET /api/ocpi/cpo/2.2/locations, one row per location with name, address, city, postal code, country, coordinates, operator, suboperator, owner and brand, parking type, access type and access restrictions, facilities, time zone, 24/7 opening, EVSE and connector counts, EVSE status counts, available EVSEs, EVSE IDs, connector standards (CCS, CHAdeMO, Type 2, Tesla), AC or DC power types, maximum power in kW and the pricing IDs of its connectors.
- **Charging location details by ID**: GET /api/ocpi/cpo/2.2/locations/{id}, the same location plus predicted occupancy by hour for the next 7 days, roaming partners (which MSP cards and apps work there) and derived opening times.
- **Charging location by EVSE ID**: GET /api/ocpi/cpo/2.2/evse/{evse_id}, the location behind an eMI3 EVSE ID such as NL\*EVN\*E30332\*9785, with that EVSE's own real-time status in `evseStatus`.
- **Charging prices**: GET /prices, every ad hoc (pay as you go), MSP and CPO subscription price with partner, product, subscription type and fee, currency, VAT and the price per kWh, per session, per hour and per parking hour, excluding VAT.
- **Charging prices by pricing ID**: GET /prices/{id} for the pricing IDs you name.
- **Pricing IDs per connector**: GET /prices/connector_prices, which links every location, EVSE and connector to its pricing IDs and product IDs.
- **CPO tariffs**: GET /api/ocpi/cpo/2.2/tariffs, the raw OCPI tariffs operators shared, with currency, CPO tariff ID and price components.
- **Changes only**: a changed since and changed until window returns only the records updated in it, for an hourly or daily sync.
- **OCPI 2.2 or 2.1.1**: pick the version your license was set up for.
- **Pay only for records**: empty answers and lookups the API refuses are recorded as a free row that says why, never charged.

Only GET routes are called. The actor never performs the OCPI credentials handshake, never registers a PATCH endpoint and never changes anything on your Eco-Movement account.

### How to use it

1. Get an Eco-Movement Data API token. Tokens are issued to organizations under a data license; ask your Eco-Movement contact or support@eco-movement.com.
2. Paste the token into the API token field, or set the DATA_API_KEY environment secret. The actor sends it as `Authorization: Token <token>`, exactly as the docs show, and removes it from everything it logs.
3. Pick a mode, set the OCPI version and an optional changed since date, add IDs for the per-record modes, and run.
4. Download the dataset as JSON, CSV or Excel, or connect it to your workflow through the Apify API, webhooks or integrations.

A missing or rejected token ends the run cleanly with a status message that explains what to change, and nothing is charged.

### Input

| Field | Modes | Description |
| --- | --- | --- |
| `mode` | all | `locations` (default), `locationDetails`, `evse`, `prices`, `priceDetails`, `connectorPrices` or `tariffs` |
| `dateFrom`, `dateTo` | locations, locationDetails, tariffs, prices, priceDetails | Only records changed in this window; a date or an ISO 8601 date-time, UTC |
| `locationIds` | locationDetails | Location IDs from the `id` column |
| `evseIds` | evse | eMI3 EVSE IDs such as `NL*EVN*E30332*9785` |
| `pricingIds` | priceDetails | Pricing IDs from the `pricingIds` column |
| `ocpiVersion` | locations, locationDetails, evse, tariffs | `2.2` (default) or `2.1.1` |
| `maxResults` | all | The most rows this run returns and charges for (default 100) |
| `requestsPerMinute` | all | Pacing for calls to Eco-Movement (default 60; pricing routes are always held to 20) |
| `apiKey` | all | Your Eco-Movement Data API token |

Location and tariff lists page with `limit` (up to 1,000) and `offset`, following the `Link` and `X-Total-Count` headers. Pricing lists page up to 10,000 at a time with the `X-Last-Record` cursor, which never skips rows. Per-ID modes take up to 1,000 IDs per run.

### Output

One row per location, price, connector pricing link or tariff. Example location row (`record` shortened):

```json
{
    "mode": "locations",
    "modeLabel": "Charging locations",
    "found": true,
    "recordType": "location",
    "id": "b2345832-4f3c-11e8-a38e-42010a840002",
    "name": "Allego DEALLEGO000453",
    "address": "Eugen-Ensslin-Strasse 2",
    "city": "Kehl",
    "postalCode": "77694",
    "state": "Baden-Wuerttemberg",
    "country": "DEU",
    "countryCode": "NL",
    "partyId": "ECO",
    "latitude": 48.57923129,
    "longitude": 7.80925827,
    "operatorName": "Allego",
    "parkingType": "PARKING_LOT",
    "accessType": "Public",
    "facilities": ["CARPOOL_PARKING", "FUEL_STATION", "RESTAURANT", "SERVICE", "STORE"],
    "timeZone": "Europe/Berlin",
    "openTwentyFourSeven": true,
    "evseCount": 2,
    "connectorCount": 3,
    "availableEvseCount": 2,
    "evseStatuses": { "AVAILABLE": 2 },
    "evseIds": ["DEALLEGO0004532", "DEALLEGO0004531"],
    "connectorStandards": ["IEC_62196_T2", "CHADEMO", "IEC_62196_T2_COMBO"],
    "powerTypes": ["AC_3_PHASE", "DC"],
    "maxPowerKw": 50,
    "pricingIds": ["95ab0f04-c08b-11ed-bb9e-42010a0150d0", "7cf2904b-bfc2-11ed-bb9e-42010a0150d0"],
    "lastUpdated": "2022-07-19T14:45:16Z",
    "record": { "evses": [] },
    "note": null
}
```

Example price row:

```json
{
    "mode": "prices",
    "recordType": "price",
    "found": true,
    "id": "fab0e7600095938398c71e7d79fb50b2204db3f34e845b1d79f2fee42aba3fd0",
    "partner": "Vattenfall",
    "countryCode": "NL",
    "productName": "Vattenfall pricing",
    "subscriptionType": "n/a",
    "currency": "EUR",
    "energyPrice": 0.367,
    "flatPrice": null,
    "timePrice": null,
    "vatPercent": 21,
    "elementCount": 1,
    "lastUpdated": "2024-02-01T20:16:22Z"
}
```

`maxPowerKw` is the highest `max_electric_power` of the location's connectors, in kW. Price columns show the first component of each type (ENERGY per kWh, FLAT per session, TIME per hour, PARKING_TIME per hour); every element with its time, power and duration restrictions stays in `record`.

### Pricing

| Event | Price | Charged for |
| --- | --- | --- |
| `charging-location` | 0.01 USD | Each location from the locations list or an EVSE ID lookup |
| `charging-location-detailed` | 0.02 USD | Each location read by ID, with predicted occupancy and roaming |
| `charging-price` | 0.005 USD | Each price, tariff or connector pricing link |

Empty answers and refused or invalid lookups are never charged. Eco-Movement bills your organization separately under your own license.

### FAQ

#### What is the Eco-Movement Data API?

It is Eco-Movement's outbound API for EV charging infrastructure data, built on the OCPI protocol used across the e-mobility industry. It serves charging locations, EVSEs (charge points), connectors, real-time status, prices and tariffs, enriched with attributes OCPI does not carry, such as access restrictions, predicted occupancy, roaming partners and truck parking details.

#### Do I need my own Eco-Movement token?

Yes. This actor is bring your own key: it calls Eco-Movement with your organization's Data API token, and your Eco-Movement license decides which countries, attributes and endpoints you can read. Eco-Movement does not offer self serve tokens.

#### How do I get real-time charger availability?

Run the charging locations mode: every row counts EVSEs per status (AVAILABLE, CHARGING, BLOCKED, OUTOFORDER, INOPERATIVE and more) in `evseStatuses`. For a fast sync, set changed since to a few minutes ago so only the changed locations come back. For one charger, use the EVSE ID mode and read `evseStatus`. Eco-Movement recommends PATCH push updates for high volume real-time feeds, which need your own receiving server and are not part of this actor.

#### How do I find what charging costs at a station?

Read the location, copy its `pricingIds`, then run charging prices by pricing ID. Or download all prices and the pricing IDs per connector list and join them on the pricing ID. Prices cover ad hoc (pay as you go), MSP card and CPO subscription products, excluding VAT, with the VAT rate alongside.

#### What is the difference between prices and tariffs?

Tariffs are the raw OCPI tariffs operators shared with Eco-Movement. Prices are more complete: they combine several sources and add the product, subscription and VAT details. Eco-Movement recommends prices.

#### Which OCPI version should I use?

The one your Eco-Movement license was set up for, usually 2.2. The 2.1.1 routes return the same locations in the older OCPI shape. The pricing routes do not depend on the version.

#### How many charging stations can I download?

A full license can return more than 100,000 locations. Set maximum results to what you need; the actor pages through 1,000 locations at a time and the pricing lists 10,000 at a time.

#### What does it cost?

0.01 USD per location, 0.02 USD per detailed location and 0.005 USD per price, tariff or connector pricing link, plus whatever your Eco-Movement license costs. Empty and refused lookups are free.

### Keyword map

EV charging stations API, EV charger data API, charging station locations API, charge point data, OCPI API, OCPI 2.2 locations, EVSE data, EV connector types, CCS CHAdeMO Type 2 data, real-time charger availability API, EV charging prices API, charging tariffs, ad hoc charging price, MSP roaming data, EV charging map data, charge point operator data, EV infrastructure data, Eco-Movement API, Eco-Movement Data API.

### Routes and verification

| Mode | Route | Source | Probe with an invalid token |
| --- | --- | --- | --- |
| Charging locations | GET /api/ocpi/cpo/2.2/locations | reference/get-all-locations | 401 `Invalid authorization token` |
| Location details by ID | GET /api/ocpi/cpo/2.2/locations/{id} | reference/get-specific-location | 401 `Invalid authorization token` |
| Location by EVSE ID | GET /api/ocpi/cpo/2.2/evse/{evse_id} | reference/get-location-using-evse | 401 `Invalid authorization token` |
| CPO tariffs | GET /api/ocpi/cpo/2.2/tariffs | reference/get-tariffs | 401 `Invalid authorization token` |
| OCPI 2.1.1 | GET /api/ocpi/cpo/2.1.1/locations and the same routes | v2.1.1 reference pages | 401 `Invalid authorization token` |
| Charging prices | GET /prices | reference/get-prices-new | 401 `Invalid authorization token` |
| Prices by pricing ID | GET /prices/{id} | reference/get-specific-price-new | 401 `Invalid authorization token` |
| Pricing IDs per connector | GET /prices/connector_prices | reference/get-connector-prices | 401 `Invalid authorization token` |

Invented routes on the same host (/api/ocpi/cpo/2.2/chargers, /pricez) answered 404 `The route ... could not be found.` on both probe rounds, so the probe tells real routes from invented ones. The credentials handshake route, the Belgium DATEX II feed (a separate host and token) and the reporting platform downloads are not wrapped.

### Licensing and data use

This actor works only with your own Eco-Movement token, and your license agreement with Eco-Movement applies to the data it returns, including where you may show it and whether you may pass it on. This actor is not affiliated with or endorsed by Eco-Movement B.V.

# Actor input Schema

## `mode` (type: `string`):

Charging locations lists every location your license covers, with EVSEs, connectors, power and real-time status. Location details by ID adds predicted occupancy, roaming partners and derived opening times. Location by EVSE ID finds the location of chosen EVSEs. Charging prices lists ad hoc and MSP prices; prices by pricing ID reads chosen ones. Pricing IDs per connector links every connector to its pricing IDs. CPO tariffs lists the raw OCPI tariffs operators shared.

## `dateFrom` (type: `string`):

Optional. Only records that changed on or after this moment, as a date (2026-10-01, midnight UTC) or an ISO 8601 date-time such as 2026-10-01T08:00:00Z. Locations, location details, tariffs, prices and prices by ID. Leave empty for the full list.

## `dateTo` (type: `string`):

Optional. Only records that changed before this moment, as a date or an ISO 8601 date-time. Times are UTC.

## `locationIds` (type: `array`):

Location details mode. One location ID per line, from the id column of the charging locations mode.

## `evseIds` (type: `array`):

Location by EVSE ID mode. One eMI3 EVSE ID per line, such as NL*EVN*E30332\*9785 or DEALLEGO0004532.

## `pricingIds` (type: `array`):

Prices by pricing ID mode. One pricing ID per line, from the pricingIds column of the locations or pricing IDs per connector modes.

## `ocpiVersion` (type: `string`):

Which OCPI version of the locations, EVSE and tariffs routes to read. Use the version your Eco-Movement license was set up for. The pricing routes are the same for both.

## `maxResults` (type: `integer`):

The most rows this run returns and charges for. A full country can hold tens of thousands of locations, and a full license over 100,000.

## `requestsPerMinute` (type: `integer`):

Pacing for calls to Eco-Movement. The pricing routes are always held to 20 a minute, their documented limit of 1200 an hour per token. Throttled calls are retried after a pause.

## `apiKey` (type: `string`):

Your Eco-Movement Data API token, as Eco-Movement issued it, without the word Token in front. Stored as a secret, sent only in the Authorization header to api.eco-movement.com and never logged. You can instead set the DATA_API_KEY environment secret.

## Actor input object example

```json
{
  "mode": "locations",
  "ocpiVersion": "2.2",
  "maxResults": 100,
  "requestsPerMinute": 60
}
```

# Actor output Schema

## `records` (type: `string`):

One row per location, price, connector pricing link or tariff the chosen mode read.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/ev-charging-stations-api").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/ev-charging-stations-api").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call nabeelbaghoor/ev-charging-stations-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/ev-charging-stations-api"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/vUVFAXZ5kH2lGuuYz/builds/XA16doHadeyfMWoet/openapi.json
