Public API for AED data
Build apps, dashboards, and emergency tools on top of Malta's crowdsourced AED dataset. JSON, CORS-enabled, no API key required.
Quick start
All endpoints are read-only and return JSON. Try one in your terminal or browser:
curl https://aedmt.life/api/public/v1/aeds?limit=5const res = await fetch("https://aedmt.life/api/public/v1/aeds?limit=5");
const { data, meta } = await res.json();
console.log(meta.total, data);Authentication
None required. The API is intentionally open so anyone — first responders, researchers, journalists — can use it without friction.
Rate limit
60 requests per minute per IP. Each response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers. Exceed it and you'll receive HTTP 429 with a Retry-After header.
Errors
All errors return JSON with an error.code (machine-readable) and error.message (human-readable). Status codes follow standard HTTP conventions: 400, 404, 429, 500.
Response shape
Successful responses are wrapped in a data envelope with optional meta. Errors are wrapped in error.
{
"data": { ... } | [ ... ],
"meta": { "total": 101, "limit": 100, "offset": 0, "returned": 100 }
}{
"error": {
"code": "rate_limited",
"message": "Too many requests. Try again in 42s."
}
}Write access (POST endpoints)
POST endpoints require a personal API key. Generate one from your account, then send it on every request:
Authorization: Bearer aedmt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxKeys are scoped (e.g. write:suggestions, write:reports). The full key value is shown only once at creation time. Revoke compromised keys at any time.
Endpoints
/api/public/v1/aedsList all approved AED locations.
Query parameters
| Name | Type | Description |
|---|---|---|
| indoor | true | false | Filter by indoor/outdoor placement. |
| locality | string | Case-insensitive locality match (e.g. "Sliema"). |
| limit | number (1–500) | Max items per page. Default 100. |
| offset | number (0–10000) | Pagination offset. Default 0. |
curl https://aedmt.life/api/public/v1/aeds?indoor=true&locality=Sliema{
"data": [
{
"id": "00000000-0000-0000-0000-000000000000",
"name": "Sliema Pharmacy AED",
"latitude": 35.913,
"longitude": 14.503,
"address": "Tower Road, Sliema",
"locality": "Sliema",
"indoor": false,
"access_24_7": true,
"floor": null,
"contact_phone": null,
"photo_url": null,
"last_verified_at": "2026-04-12T10:00:00.000Z",
"created_at": "2025-08-01T08:30:00.000Z"
}
],
"meta": {
"total": 101,
"limit": 100,
"offset": 0,
"returned": 1
}
}GET https://aedmt.life/api/public/v1/aeds?indoor=true&locality=Sliema&limit=5/api/public/v1/aeds/{id}Fetch a single AED by UUID.
curl https://aedmt.life/api/public/v1/aeds/{id}{
"data": {
"id": "00000000-0000-0000-0000-000000000000",
"name": "Sliema Pharmacy AED",
"latitude": 35.913,
"longitude": 14.503,
"indoor": false,
"access_24_7": true
}
}GET https://aedmt.life/api/public/v1/aeds/%7Bid%7D/api/public/v1/aeds/nearestReturn the AEDs closest to a given coordinate.
Query parameters
| Name | Type | Description |
|---|---|---|
| lat* | number (-90 to 90) | Latitude in decimal degrees. |
| lng* | number (-180 to 180) | Longitude in decimal degrees. |
| limit | number (1–50) | Max results. Default 5. |
| indoor | true | false | Restrict to indoor or outdoor units. |
curl https://aedmt.life/api/public/v1/aeds/nearest?lat=35.91&lng=14.42{
"data": [
{
"id": "00000000-0000-0000-0000-000000000000",
"name": "Sliema Pharmacy AED",
"latitude": 35.913,
"longitude": 14.503,
"distance_m": 142
}
],
"meta": {
"from": {
"lat": 35.914,
"lng": 14.502
},
"returned": 1
}
}GET https://aedmt.life/api/public/v1/aeds/nearest?lat=35.91&lng=14.42&limit=5/api/public/v1/statsAggregate coverage statistics for the dataset.
curl https://aedmt.life/api/public/v1/stats{
"data": {
"total": 101,
"indoor": 28,
"outdoor": 41,
"unknown_placement": 32,
"malta": 87,
"gozo": 14,
"recently_verified": 22,
"generated_at": "2026-05-05T08:00:00.000Z"
}
}GET https://aedmt.life/api/public/v1/stats/api/public/v1/aeds/suggestionsSubmit a new AED suggestion. Goes into the moderation queue.
{
"name": "Pharmacy AED",
"latitude": 35.913,
"longitude": 14.503,
"address": "Tower Road, Sliema",
"indoor": true,
"access_24_7": false,
"floor": "Ground",
"contact_phone": "+356 1234 5678"
}curl -X POST 'https://aedmt.life/api/public/v1/aeds/suggestions' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"name": "Pharmacy AED",
"latitude": 35.913,
"longitude": 14.503,
"address": "Tower Road, Sliema",
"indoor": true,
"access_24_7": false,
"floor": "Ground",
"contact_phone": "+356 1234 5678"
}'{
"data": {
"id": "00000000-0000-0000-0000-000000000000",
"status": "pending",
"created_at": "2026-05-09T12:00:00.000Z"
}
}Need one? Generate an API key. Sent as Authorization: Bearer ….
POST https://aedmt.life/api/public/v1/aeds/suggestions/api/public/v1/aeds/{id}/reportsFlag an issue with an existing AED (broken, battery, vandalised, etc.).
{
"report_type": "battery_issue",
"message": "Battery indicator is red.",
"photo_url": "https://example.com/evidence.jpg"
}curl -X POST 'https://aedmt.life/api/public/v1/aeds/{id}/reports' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"report_type": "battery_issue",
"message": "Battery indicator is red.",
"photo_url": "https://example.com/evidence.jpg"
}'{
"data": {
"id": "00000000-0000-0000-0000-000000000000",
"created_at": "2026-05-09T12:00:00.000Z"
}
}Need one? Generate an API key. Sent as Authorization: Bearer ….
POST https://aedmt.life/api/public/v1/aeds/%7Bid%7D/reportsAttribution & licence
Data is contributed by the community and partly sourced from OpenStreetMap. Please credit "aed.mt" when reusing the data and link back to https://aedmt.life. For commercial or high-volume usage, please get in touch.