Quick start
- Ask for a key. Write to hello@cmstechnosolutions.com with the name of your product, what it does with the data, and a contact address. We make the key and send it to you. It is shown once, so store it safely.
-
Keep it on your server. Put it in an environment variable. Never in a web page or mobile app that others can open.
export CHARGELK_KEY=clk_YOUR_KEY -
Make a request. The nearest chargers within 10 km of Colombo Fort:
curl "https://chargelk.com/api/v1/stations?near=6.9271,79.8612&radius_km=10" \ -H "Authorization: Bearer $CHARGELK_KEY"
The API is read only. It returns chargers, never customers or owners.
Authentication
Send your key with every request, in the Authorization header:
Authorization: Bearer clk_YOUR_KEY
X-Api-Key: clk_YOUR_KEY works too. Base address: https://chargelk.com/api/v1. Everything is JSON, over HTTPS.
/stations
List stations with their chargers
A station is a site with one or more chargers. Give "near" to get the closest first, each with distance_km.
Parameters
| Name | Type | What it does |
|---|---|---|
nearquery |
string | A point as "lat,lng", for example 6.9271,79.8612. Returns stations within radius_km, nearest first. |
radius_kmquery |
number | Used with near. Default 25. |
cityquery |
string | Only stations in this city, spelled as in the data. |
statusquery |
string | Only chargers with this status. Stations with no matching charger are left out. availableoccupiedofflinefaultedmaintenance |
connectorquery |
string | Only chargers with this connector. CCS2CHAdeMOGBTType2 |
pagequery |
integer default 1 | Which page of results. 1 is the first. |
per_pagequery |
integer default 100 | How many stations on a page, up to 200. |
Example request
curl "https://chargelk.com/api/v1/stations?near=6.9271,79.8612&radius_km=10" \
-H "Authorization: Bearer $CHARGELK_KEY"
const res = await fetch("https://chargelk.com/api/v1/stations?near=6.9271,79.8612&radius_km=10", {
headers: { Authorization: `Bearer ${process.env.CHARGELK_KEY}` },
});
if (!res.ok) throw new Error((await res.json()).message);
const { data, meta } = await res.json();
console.log(data);
import os, requests
res = requests.get(
"https://chargelk.com/api/v1/stations?near=6.9271,79.8612&radius_km=10",
headers={"Authorization": "Bearer " + os.environ["CHARGELK_KEY"]},
timeout=10,
)
res.raise_for_status()
print(res.json()["data"])
<?php
$ch = curl_init("https://chargelk.com/api/v1/stations?near=6.9271,79.8612&radius_km=10");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("CHARGELK_KEY")],
]);
$body = json_decode(curl_exec($ch), true);
print_r($body["data"]);
Example response 200 OK
{
"data": [
{
"id": 12,
"name": "Galle Face Car Park",
"address": "1 Galle Road, Colombo 3",
"city": "Colombo",
"location": {
"lat": 6.9271,
"lng": 79.8438
},
"opening_hours": "Daily 06:00 to 22:00",
"amenities": [
"seating",
"washrooms",
"wifi"
],
"distance_km": 1.4,
"chargers": [
{
"id": "CP-001",
"status": "available",
"status_checked_at": "2026-11-02T09:14:52+00:00",
"connector": {
"type": "CCS2",
"current": "DC",
"count": 1
},
"power_kw": 30,
"price": {
"currency": "LKR",
"per_kwh": {
"lkr": 100,
"cents": 10000
},
"idle_fee_per_minute": {
"lkr": 0,
"cents": 0
},
"tax_included": true
},
"planned_outage": null
}
]
}
],
"meta": {
"total": 1,
"page": 1,
"per_page": 100,
"generated_at": "2026-11-02T09:15:01+00:00"
}
}
Errors this can return
/stations/{id}
One station
Parameters
| Name | Type | What it does |
|---|---|---|
id requiredpath |
integer |
Example request
curl "https://chargelk.com/api/v1/stations/12" \
-H "Authorization: Bearer $CHARGELK_KEY"
const res = await fetch("https://chargelk.com/api/v1/stations/12", {
headers: { Authorization: `Bearer ${process.env.CHARGELK_KEY}` },
});
if (!res.ok) throw new Error((await res.json()).message);
const { data, meta } = await res.json();
console.log(data);
import os, requests
res = requests.get(
"https://chargelk.com/api/v1/stations/12",
headers={"Authorization": "Bearer " + os.environ["CHARGELK_KEY"]},
timeout=10,
)
res.raise_for_status()
print(res.json()["data"])
<?php
$ch = curl_init("https://chargelk.com/api/v1/stations/12");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("CHARGELK_KEY")],
]);
$body = json_decode(curl_exec($ch), true);
print_r($body["data"]);
Example response 200 OK
{
"data": {
"id": 12,
"name": "Galle Face Car Park",
"address": "1 Galle Road, Colombo 3",
"city": "Colombo",
"location": {
"lat": 6.9271,
"lng": 79.8438
},
"opening_hours": "Daily 06:00 to 22:00",
"amenities": [
"seating",
"washrooms",
"wifi"
],
"chargers": [
{
"id": "CP-001",
"status": "available",
"status_checked_at": "2026-11-02T09:14:52+00:00",
"connector": {
"type": "CCS2",
"current": "DC",
"count": 1
},
"power_kw": 30,
"price": {
"currency": "LKR",
"per_kwh": {
"lkr": 100,
"cents": 10000
},
"idle_fee_per_minute": {
"lkr": 0,
"cents": 0
},
"tax_included": true
},
"planned_outage": null
}
]
},
"meta": {
"generated_at": "2026-11-02T09:15:01+00:00"
}
}
Errors this can return
/chargers/{id}
One charger by its id
Parameters
| Name | Type | What it does |
|---|---|---|
id requiredpath |
string | The charger id, for example CP-001. |
Example request
curl "https://chargelk.com/api/v1/chargers/CP-001" \
-H "Authorization: Bearer $CHARGELK_KEY"
const res = await fetch("https://chargelk.com/api/v1/chargers/CP-001", {
headers: { Authorization: `Bearer ${process.env.CHARGELK_KEY}` },
});
if (!res.ok) throw new Error((await res.json()).message);
const { data, meta } = await res.json();
console.log(data);
import os, requests
res = requests.get(
"https://chargelk.com/api/v1/chargers/CP-001",
headers={"Authorization": "Bearer " + os.environ["CHARGELK_KEY"]},
timeout=10,
)
res.raise_for_status()
print(res.json()["data"])
<?php
$ch = curl_init("https://chargelk.com/api/v1/chargers/CP-001");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("CHARGELK_KEY")],
]);
$body = json_decode(curl_exec($ch), true);
print_r($body["data"]);
Example response 200 OK
{
"data": {
"id": "CP-001",
"status": "available",
"status_checked_at": "2026-11-02T09:14:52+00:00",
"connector": {
"type": "CCS2",
"current": "DC",
"count": 1
},
"power_kw": 30,
"price": {
"currency": "LKR",
"per_kwh": {
"lkr": 100,
"cents": 10000
},
"idle_fee_per_minute": {
"lkr": 0,
"cents": 0
},
"tax_included": true
},
"planned_outage": null,
"station_id": 12
},
"meta": {
"generated_at": "2026-11-02T09:15:01+00:00"
}
}
Errors this can return
What the fields mean
Charger status
| Value | Meaning |
|---|---|
| available | Online and free: plug in and start. |
| occupied | Online and charging, or a vehicle is plugged in. |
| offline | Not connected to ChargeLK right now (no contact for 10 minutes). |
| faulted | The charger reports a fault and is being repaired. |
| maintenance | Under announced planned maintenance. See planned_outage for when it is back. |
status_checked_at is when the charger last spoke to us. It is a live reading, not a forecast: a charger that is free now may be taken a minute later.
Connector and power
connector.type is CCS2, CHAdeMO, GBT (GB/T) or Type2. connector.current is AC (Type 2) or DC (fast). power_kw is the most the charger can deliver.
Price
Prices are in Sri Lankan rupees and include any tax. per_kwh is what a driver pays for each kWh the charger's meter counts. idle_fee_per_minute is zero unless the charger bills for staying plugged in after charging. Each price is given as lkr (rupees, with decimals) and cents (whole cents, for exact arithmetic). The price a driver pays is fixed when they press Start.
Facilities
amenities lists what the site offers:
seatingSeatingwashroomsWashroomsfoodFood and drinkwifiWi-FishelterCovered parkingsecuritySecurity (CCTV or guard)accessibleStep-free access
Planned maintenance
planned_outage is null, or an object with starts_at, ends_at and active for maintenance within the next 14 days or happening now. While it is active the status is maintenance.
Times
All times are ISO 8601 with an offset, such as 2026-11-02T09:14:52+00:00.
Limits and errors
Each key may make 60 requests a minute unless we agreed another figure. Every response carries X-RateLimit-Limit and X-RateLimit-Remaining.
401The key is missing, wrong, expired or revoked.{
"message": "An API key is required. Send it as \"Authorization: Bearer <key>\".",
"code": "missing_api_key"
}
404No such station or charger, or it is not in service.{
"message": "Not Found."
}
422A parameter is not valid. "errors" says which.{
"message": "The status field must be one of available, occupied, offline, faulted, maintenance.",
"errors": {
"status": [
"The selected status is invalid."
]
}
}
429This key used up its requests for the minute. Wait for the next one.{
"message": "Too many requests for this API key. Wait a minute and try again.",
"code": "rate_limited"
}
Errors always carry a message you can show or log. Test code in your software, not the message wording.
Good practice
- Ask for what you need. Use
nearandradius_km, orcity, instead of fetching every station on each request. - Do not poll faster than you need. Status is updated as each charger reports it, usually within seconds. Once every 30 seconds for an area is plenty for a map, and asking faster only uses up your allowance.
- Show how old the reading is. Use
status_checked_at, and treatofflineas unknown, not as broken. - Use
centsfor sums andlkrfor display. - Keep the key on your server. If it leaks, tell us and we will revoke it and make a new one.
- Ignore fields you do not know. Version 1 only ever gains new, optional fields.
Versions and support
Version 1 only gets new, optional fields. A change that could break your software would be a version 2, announced to every key holder first, with the old version kept running for a stated time.
The full machine-readable description (OpenAPI 3.0) can be read here, or fetched by your tools from /api/v1/openapi.json. Import it into Postman, Insomnia or Swagger UI, or generate a client from it.
Questions, a higher limit, or a problem with a key: hello@cmstechnosolutions.com.