248 lines
4.8 KiB
Markdown
248 lines
4.8 KiB
Markdown
# Waste Collection API — OpenAPI Specification
|
|
|
|
**Base URL:** `http://localhost:8000`
|
|
**Version:** 1.0.0
|
|
**Purpose:** Return waste collection schedules for German municipalities via push notification targets (email, Telegram, etc.)
|
|
|
|
---
|
|
|
|
## API Endpoints
|
|
|
|
### `GET /health`
|
|
Health check.
|
|
|
|
**Response `200`**
|
|
```json
|
|
{ "status": "ok" }
|
|
```
|
|
|
|
---
|
|
|
|
### `GET /sources`
|
|
List all available source IDs (e.g. `abfall_io`, `awm_muenchen_de`, `ics`).
|
|
|
|
**Response `200`**
|
|
```json
|
|
{
|
|
"count": 3,
|
|
"sources": [
|
|
{ "id": "ics", "name": "Generic ICS / iCal URL" },
|
|
{ "id": "abfall_io", "name": "Abfall.IO (Germany)" },
|
|
{ "id": "awm_muenchen_de","name": "AWM München (Germany)" }
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### `GET /sources/{source_id}`
|
|
Describe required params for a given source.
|
|
|
|
**Path params:**
|
|
`source_id` — e.g. `ics`, `abfall_io`, `awm_muenchen_de`
|
|
|
|
**Response `200`**
|
|
```json
|
|
{
|
|
"id": "abfall_io",
|
|
"name": "Abfall.IO (Germany)",
|
|
"params": [
|
|
{ "name": "key", "type": "string", "required": true, "example": "8215c62763967916979e0e8566b6172e" },
|
|
{ "name": "f_id_kommune","type": "integer","required": true, "example": 2999 },
|
|
{ "name": "f_id_strasse","type": "integer","required": true, "example": 1087 }
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### `POST /collections/ics`
|
|
Fetch waste collections from a generic ICS/iCal URL.
|
|
|
|
**Request body**
|
|
```json
|
|
{
|
|
"url": "https://example.com/kalender.ics",
|
|
"count": 10
|
|
}
|
|
```
|
|
| Field | Type | Required | Default | Description |
|
|
|-------|------|----------|---------|-------------|
|
|
| `url` | string | ✅ | — | Direct URL to `.ics` file |
|
|
| `count` | integer | ❌ | 20 | Max entries to return |
|
|
|
|
**Response `200`**
|
|
```json
|
|
{
|
|
"source": "ics",
|
|
"url": "https://example.com/kalender.ics",
|
|
"collections": [
|
|
{
|
|
"date": "2026-04-08",
|
|
"type": "Restmülltonne",
|
|
"daysUntil": 4,
|
|
"icon": "mdi:trash-can"
|
|
},
|
|
{
|
|
"date": "2026-04-27",
|
|
"type": "Papiertonne",
|
|
"daysUntil": 23,
|
|
"icon": "mdi:paper-bin"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### `POST /collections/abfall_io`
|
|
Fetch collections via Abfall.IO (many German municipalities).
|
|
|
|
**Request body**
|
|
```json
|
|
{
|
|
"key": "8215c62763967916979e0e8566b6172e",
|
|
"f_id_kommune": 2999,
|
|
"f_id_strasse": 1087,
|
|
"count": 20
|
|
}
|
|
```
|
|
|
|
**Response `200`** — same shape as `/collections/ics` with `source: "abfall_io"`.
|
|
|
|
---
|
|
|
|
### `POST /collections/awm_muenchen_de`
|
|
Fetch collections for Munich via AWM.
|
|
|
|
**Request body**
|
|
```json
|
|
{
|
|
"street": "Bahnstr.",
|
|
"house_number": "11",
|
|
"count": 20
|
|
}
|
|
```
|
|
|
|
**Response `200`** — same shape as `/collections/ics` with `source: "awm_muenchen_de"`.
|
|
|
|
---
|
|
|
|
### `POST /notify`
|
|
Queue a notification for a future collection.
|
|
|
|
**Request body**
|
|
```json
|
|
{
|
|
"source_id": "ics",
|
|
"collection": {
|
|
"date": "2026-04-08",
|
|
"type": "Restmülltonne",
|
|
"daysUntil": 4,
|
|
"icon": "mdi:trash-can"
|
|
},
|
|
"notify_at_days_before": 1,
|
|
"channels": ["telegram"],
|
|
"chat_id": 1320170074
|
|
}
|
|
```
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `source_id` | string | ✅ | Source that returned this collection |
|
|
| `collection` | object | ✅ | A single collection entry |
|
|
| `notify_at_days_before` | integer | ❌ | Days before collection to fire (default: 1) |
|
|
| `channels` | string[] | ✅ | `["telegram"]` (more coming) |
|
|
| `chat_id` | integer | ✅ | Telegram chat ID to notify |
|
|
|
|
**Response `200`**
|
|
```json
|
|
{
|
|
"ok": true,
|
|
"notification_id": "notif_abc123",
|
|
"message": "Reminder set for 2026-04-08: Restmülltonne"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### `GET /notifications`
|
|
List all active notification rules.
|
|
|
|
**Response `200`**
|
|
```json
|
|
{
|
|
"count": 1,
|
|
"notifications": [
|
|
{
|
|
"id": "notif_abc123",
|
|
"source_id": "ics",
|
|
"collection_type": "Restmülltonne",
|
|
"collection_date": "2026-04-08",
|
|
"notify_at_days_before": 1,
|
|
"channels": ["telegram"],
|
|
"chat_id": 1320170074,
|
|
"fired": false
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### `DELETE /notifications/{notification_id}`
|
|
Delete a notification rule.
|
|
|
|
**Response `200`**
|
|
```json
|
|
{ "ok": true, "deleted": "notif_abc123" }
|
|
```
|
|
|
|
---
|
|
|
|
## Error Responses
|
|
|
|
All endpoints return errors in this shape:
|
|
|
|
```json
|
|
{
|
|
"error": "Human-readable error message",
|
|
"detail": "Optional technical detail"
|
|
}
|
|
```
|
|
|
|
| Status | Meaning |
|
|
|--------|---------|
|
|
| `400` | Bad request — missing or invalid params |
|
|
| `404` | Source not found |
|
|
| `422` | Unprocessable entity — source returned no data |
|
|
| `500` | Internal server error |
|
|
|
|
---
|
|
|
|
## Data Models
|
|
|
|
### `Collection`
|
|
```json
|
|
{
|
|
"date": "YYYY-MM-DD",
|
|
"type": "Human-readable waste type string",
|
|
"daysUntil": 4,
|
|
"icon": "mdi:icon-name"
|
|
}
|
|
```
|
|
|
|
### `Notification`
|
|
```json
|
|
{
|
|
"id": "notif_abc123",
|
|
"source_id": "ics | abfall_io | awm_muenchen_de",
|
|
"collection_type": "Restmülltonne",
|
|
"collection_date": "2026-04-08",
|
|
"notify_at_days_before": 1,
|
|
"channels": ["telegram"],
|
|
"chat_id": 1320170074,
|
|
"fired": false
|
|
}
|
|
```
|