FOR EV APPS AND INTEGRATORS
Nearby chargers API
A read-only endpoint that returns shared, host-listed EV chargers near any location, sorted by distance. EV navigation apps, dashboards and assistants can call it directly — no account or key needed today.
Endpoint
One endpoint, GET only. Send the caller's location and get back the closest active host chargers.
GET /api/public/chargers/nearbyBase URL: this API is served by this site — send requests to this domain, e.g.
https://neighbor-charge-network.lovable.app/api/public/chargers/nearby.Query parameters
All parameters are sent as URL query strings.
| Parameter | Required | Range | Description |
|---|---|---|---|
lat | Yes | −90 to 90 | Latitude of the search origin, in decimal degrees. |
lng | Yes | −180 to 180 | Longitude of the search origin, in decimal degrees. |
radius_km | No | Default 10, max 50 | Search radius in kilometres. Anything above 50 is rejected. |
connector | No | See below | Only return chargers with this plug type. |
limit | No | 1–50, default 20 | Maximum number of results returned. |
Accepted connector values: Type 2CCS2CHAdeMOType 1Standard power point
Filters at a glance
- Distance — results are sorted nearest first and cut off at
radius_km. - Plug type — exact match on the host's listed connector, e.g.
connector=CCS2. - Speed and price — returned in every result (
power_kw,price) so your app can filter or rank client-side. - Open now — every result includes an
open_nowflag calculated against the host's opening hours (Australian Eastern time).
Example request
curl "https://neighbor-charge-network.lovable.app/api/public/chargers/nearby?lat=-27.4698&lng=153.0251&radius_km=15&connector=Type%202&limit=5"Example response
HTTP 200, application/json. Distances are rounded to 0.1 km.
{
"count": 1,
"location_precision": "suburb",
"results": [
{
"id": "9f1c2a44-1b3e-4c55-9a7b-2d6f0e8c1234",
"name": "West End driveway charger",
"suburb": "West End",
"approx_lat": -27.4821,
"approx_lng": 153.0123,
"distance_km": 1.4,
"connector": "Type 2",
"current_type": "AC",
"power_kw": 7,
"price": { "amount_cents": 30, "currency": "AUD", "unit": "kwh" },
"open_now": true,
"availability": "host-confirmed on request",
"book_url": "https://neighbor-charge-network.lovable.app/chargers/9f1c2a44-1b3e-4c55-9a7b-2d6f0e8c1234"
}
]
}| Field | Description |
|---|---|
count | Number of results in this response (may be less than the limit). |
location_precision | Always suburb — coordinates are deliberately approximate. |
approx_lat / approx_lng | Approximate charger position, suitable for map pins at suburb zoom. |
distance_km | Great-circle distance from the request origin, in kilometres. |
price | Host's listed rate in Australian cents: per kWh (unit: "kwh") or per hour (unit: "hour"). |
open_now | Whether the charger is inside the host's opening hours right now. |
availability | Always host-confirmed on request — this is not a live socket status. |
book_url | Deep link to the charger page where a driver can request a session. |
Errors
| Status | When | Body |
|---|---|---|
400 | Missing or out-of-range parameters. | { "error": "Invalid query", "issues": { ... } } — issues names each bad parameter. |
429 | Rate limit exceeded. Wait for Retry-After seconds, then retry. | { "error": "Too many requests", "retry_after_seconds": 42 } |
503 | The listing service is temporarily unavailable. Retry with backoff. | { "error": "Unavailable" } |
Rate limits and retries
- 60 requests per minute per caller IP address, counted in fixed one-minute windows.
- Every response carries
RateLimit-Limit,RateLimit-RemainingandRateLimit-Reset(seconds until the window resets). These headers are readable from browser apps. - Over the limit you get
429with aRetry-Afterheader in seconds. Wait that long before retrying — don't hammer. - On 503 or network errors, retry with exponential backoff and jitter: about 1s, 2s, 4s, up to 30s, then stop after 5 attempts.
- Never retry a 400. Fix the query parameters instead.
- Best-effort today. Limits are enforced per server instance, so exact counts can vary slightly. Design for the published numbers, not the edge cases.
async function nearby(url, attempt = 0) {
const res = await fetch(url);
if (res.status === 429) {
const wait = Number(res.headers.get("Retry-After") ?? 60);
await new Promise(r => setTimeout(r, wait * 1000));
return nearby(url, attempt + 1);
}
if (res.status === 503 && attempt < 5) {
const wait = Math.min(30, 2 ** attempt) * 1000 * (0.5 + Math.random());
await new Promise(r => setTimeout(r, wait));
return nearby(url, attempt + 1);
}
return res.json();
}Privacy limits
- Host addresses are never exposed. The endpoint returns suburb-level coordinates only — enough for a map pin, never a street address.
- Exact addresses unlock one way: a host reveals their address only after they accept a specific driver's booking request, inside the app.
- Only active listings are returned. Paused or removed chargers disappear from responses immediately.
- No personal data: responses contain no host names, contact details or booking information.
Integrating with an EV app
- CORS is open. Browser apps can call the endpoint directly from JavaScript; server-side calls work the same way.
- Cache for 60 seconds. Responses include
Cache-Control: public, max-age=60— respect it instead of polling faster. - Poll on arrival, not continuously. A good pattern is one query when a driver starts looking for a charge, and a refresh every few minutes while searching.
- Send drivers to
book_url. Sessions are confirmed by the host, so real-time availability is not guaranteed until a request is accepted. - Show prices as estimates.
priceis the host's listed rate; the final amount is agreed in the app. - Handle an empty list gracefully. New areas may have no host chargers yet —
count: 0is a normal response.
No API key required today. The endpoint is open while the network is small, within the rate limits above. If API keys are introduced later, they will be documented on this page first.