Developers

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.

JSON
REST
CORS
No auth
60 req / min

Quick start

All endpoints are read-only and return JSON. Try one in your terminal or browser:

cURL
curl https://aedmt.life/api/public/v1/aeds?limit=5
JavaScript
const 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.

Success
{
  "data": { ... } | [ ... ],
  "meta": { "total": 101, "limit": 100, "offset": 0, "returned": 100 }
}
Error
{
  "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:

Header
Authorization: Bearer aedmt_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Keys 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.

Manage your API keys

Endpoints

GET
/api/public/v1/aeds

List all approved AED locations.

Query parameters

NameTypeDescription
indoortrue | falseFilter by indoor/outdoor placement.
localitystringCase-insensitive locality match (e.g. "Sliema").
limitnumber (1–500)Max items per page. Default 100.
offsetnumber (0–10000)Pagination offset. Default 0.
Example request
curl https://aedmt.life/api/public/v1/aeds?indoor=true&locality=Sliema
Example response
{
  "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
  }
}
Try it
GET https://aedmt.life/api/public/v1/aeds?indoor=true&locality=Sliema&limit=5
GET
/api/public/v1/aeds/{id}

Fetch a single AED by UUID.

Example request
curl https://aedmt.life/api/public/v1/aeds/{id}
Example response
{
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "name": "Sliema Pharmacy AED",
    "latitude": 35.913,
    "longitude": 14.503,
    "indoor": false,
    "access_24_7": true
  }
}
Try it
GET https://aedmt.life/api/public/v1/aeds/%7Bid%7D
GET
/api/public/v1/aeds/nearest

Return the AEDs closest to a given coordinate.

Query parameters

NameTypeDescription
lat*number (-90 to 90)Latitude in decimal degrees.
lng*number (-180 to 180)Longitude in decimal degrees.
limitnumber (1–50)Max results. Default 5.
indoortrue | falseRestrict to indoor or outdoor units.
Example request
curl https://aedmt.life/api/public/v1/aeds/nearest?lat=35.91&lng=14.42
Example response
{
  "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
  }
}
Try it
GET https://aedmt.life/api/public/v1/aeds/nearest?lat=35.91&lng=14.42&limit=5
GET
/api/public/v1/stats

Aggregate coverage statistics for the dataset.

Example request
curl https://aedmt.life/api/public/v1/stats
Example response
{
  "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"
  }
}
Try it
GET https://aedmt.life/api/public/v1/stats
POST
/api/public/v1/aeds/suggestions
API key · write:suggestions

Submit a new AED suggestion. Goes into the moderation queue.

Example body
{
  "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"
}
Example request
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"
}'
Example response
{
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "status": "pending",
    "created_at": "2026-05-09T12:00:00.000Z"
  }
}
Try it

Need one? Generate an API key. Sent as Authorization: Bearer ….

POST https://aedmt.life/api/public/v1/aeds/suggestions
POST
/api/public/v1/aeds/{id}/reports
API key · write:reports

Flag an issue with an existing AED (broken, battery, vandalised, etc.).

Example body
{
  "report_type": "battery_issue",
  "message": "Battery indicator is red.",
  "photo_url": "https://example.com/evidence.jpg"
}
Example request
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"
}'
Example response
{
  "data": {
    "id": "00000000-0000-0000-0000-000000000000",
    "created_at": "2026-05-09T12:00:00.000Z"
  }
}
Try it

Need one? Generate an API key. Sent as Authorization: Bearer ….

POST https://aedmt.life/api/public/v1/aeds/%7Bid%7D/reports

Attribution & 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.