Source: https://spooly.eu/en/docs/api/maintenance

# Maintenance

The maintenance book: printers with hours, tasks with status and due date, the log, and completing or snoozing tasks.

## Get the maintenance book

`GET /maintenance`

`status` is `due`, `soon` or `ok`. `metric` is one of `hours`, `prints`, `kg`, `days`, `print_days`. `eta_days` estimates the days until due, 0 or less means overdue. It is null if Spooly does not have enough prints for an estimate yet or the part sits on the shelf as a spare. Task names come in the language of the account.

```bash
curl "https://spooly.eu/api/v1/maintenance" \
  -H "Authorization: Bearer $SPOOLY_KEY"
```

Response (200):

```
{
  "printers": [
    {
      "printer_id": "e41b7c09a3d65f28b0c94e17d2a86f35",
      "printer": "X1 Carbon von Tobi",
      "hours": 812.5,
      "prints": 640,
      "filament_kg": 41.3,
      "due_count": 1,
      "soon_count": 2,
      "health_score": 84,
      "hours_confirmed": true
    }
  ],
  "tasks": [
    {
      "id": "mc_4f60b9158e2a",
      "printer_id": "e41b7c09a3d65f28b0c94e17d2a86f35",
      "printer": "X1 Carbon von Tobi",
      "name": "Nozzle 0.4 mm",
      "status": "due",
      "metric": "kg",
      "interval": 5,
      "used": 5.2,
      "remaining": -0.2,
      "eta_days": 0,
      "snoozed_until": null,
      "last_done_at": "2026-08-12T09:30:00Z",
      "default_action": "replace"
    }
  ],
  "printers_without_plan": [],
  "due_count": 1,
  "soon_count": 2,
  "snoozed_count": 0
}
```

## Maintenance log

`GET /maintenance/log`

Newest first, without photos. `type` is one of `replace`, `clean`, `check`, `service`, `snooze`, `setup`. Deleted tasks stay in the log, but without a name.

Parameters:

- `task_id` (Query, optional): Only this task
- `printer_id` (Query, optional): Only this printer
- `limit` (Query, optional): 1 to 200, default 50
- `offset` (Query, optional): 0 to 1,000,000, default 0

```bash
curl "https://spooly.eu/api/v1/maintenance/log?task_id=mc_4f60b9158e2a" \
  -H "Authorization: Bearer $SPOOLY_KEY"
```

Response (200):

```
{
  "items": [
    {
      "id": "ml_7b34c4d1e8f2",
      "task_id": "mc_4f60b9158e2a",
      "task": "Nozzle 0.4 mm",
      "printer": "X1 Carbon von Tobi",
      "type": "replace",
      "notes": "Neue Düse 0,4 mm",
      "cost": 12.5,
      "at": "2026-08-12T09:30:00Z"
    }
  ],
  "total": 12,
  "limit": 50,
  "offset": 0
}
```

## Complete maintenance

`POST /maintenance/tasks/{task_id}/complete`

The counter starts over, the stock is deducted, the due notice goes away. Without `action`, the `default_action` of the task applies. `stock_empty` names a stock item that ran out because of this.

Parameters:

- `task_id` (Path): The `id` of the task from `GET /maintenance`
- `action` (Body, optional): `replace`, `clean` or `check`
- `notes` (Body, optional): Up to 1,000 characters
- `Idempotency-Key` (Header, optional): 1 to 128 visible ASCII characters. [Idempotency-Key](https://spooly.eu/en/docs/api#api-idempotenz)

```bash
curl -X POST "https://spooly.eu/api/v1/maintenance/tasks/mc_4f60b9158e2a/complete" \
  -H "Authorization: Bearer $SPOOLY_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action":"replace","notes":"Neue Düse 0,4 mm"}'
```

Response (200):

```
{
  "change_id": 381,
  "spool": null,
  "slot": null,
  "old_grams": null,
  "new_grams": null,
  "replayed": false,
  "task": {
    "id": "mc_4f60b9158e2a",
    "printer_id": "e41b7c09a3d65f28b0c94e17d2a86f35",
    "printer": "X1 Carbon von Tobi",
    "name": "Nozzle 0.4 mm",
    "status": "ok",
    "metric": "kg",
    "interval": 5,
    "used": 0,
    "remaining": 5,
    "eta_days": 0,
    "snoozed_until": null,
    "last_done_at": "2026-11-01T10:15:00Z",
    "default_action": "replace"
  },
  "printer": {
    "printer_id": "e41b7c09a3d65f28b0c94e17d2a86f35",
    "printer": "X1 Carbon von Tobi",
    "hours": 812.5,
    "prints": 640,
    "filament_kg": 41.3,
    "due_count": 0,
    "soon_count": 2,
    "health_score": 84,
    "hours_confirmed": true
  },
  "stock_empty": null,
  "summary": "Wartung Nozzle 0.4 mm an X1 Carbon von Tobi erledigt"
}
```

## Snooze maintenance

`POST /maintenance/tasks/{task_id}/snooze`

The task comes back after the given number of days.

Parameters:

- `task_id` (Path): The `id` of the task from `GET /maintenance`
- `days` (Body): 7, 14 or 30
- `reason` (Body, optional): Up to 200 characters
- `Idempotency-Key` (Header, optional): 1 to 128 visible ASCII characters. [Idempotency-Key](https://spooly.eu/en/docs/api#api-idempotenz)

```bash
curl -X POST "https://spooly.eu/api/v1/maintenance/tasks/mc_4f60b9158e2a/snooze" \
  -H "Authorization: Bearer $SPOOLY_KEY" \
  -H "Content-Type: application/json" \
  -d '{"days":14,"reason":"Teil ist bestellt"}'
```

Response (200):

```
{
  "change_id": 381,
  "spool": null,
  "slot": null,
  "old_grams": null,
  "new_grams": null,
  "replayed": false,
  "task": {
    "id": "mc_4f60b9158e2a",
    "printer_id": "e41b7c09a3d65f28b0c94e17d2a86f35",
    "printer": "X1 Carbon von Tobi",
    "name": "Nozzle 0.4 mm",
    "status": "due",
    "metric": "kg",
    "interval": 5,
    "used": 5.2,
    "remaining": -0.2,
    "eta_days": 0,
    "snoozed_until": "2026-11-15T10:15:00Z",
    "last_done_at": "2026-08-12T09:30:00Z",
    "default_action": "replace"
  },
  "printer": null,
  "stock_empty": null,
  "summary": "Wartung Nozzle 0.4 mm um 14 Tage verschoben"
}
```
