{
    "openapi": "3.0.0",
    "info": {
        "title": "TaskPilot API",
        "description": "TaskPilot ist eine sichere CodeIgniter 4 Demo-API für eine React-Native-App. Die API bietet Login, Access Token, Refresh Token, Rollen/Rechte, Rate Limiting, Security Logging und ein Aufgaben-CRUD mit JSON-Dateien.",
        "version": "1.0.0"
    },
    "servers": [
        {
            "url": "https://taskpilot.mia.bio",
            "description": "Live API"
        }
    ],
    "paths": {
        "/api/register": {
            "post": {
                "tags": [
                    "Auth"
                ],
                "summary": "Benutzer registrieren",
                "description": "Erstellt einen neuen Benutzer in users.json. Das Passwort wird mit password_hash() sicher gehasht. Neue Benutzer erhalten automatisch die Rolle user.",
                "operationId": "registerUser",
                "requestBody": {
                    "description": "Registrierungsdaten des neuen Benutzers.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "name",
                                    "email",
                                    "password"
                                ],
                                "properties": {
                                    "name": {
                                        "description": "Name des Benutzers. Maximal 80 Zeichen.",
                                        "type": "string",
                                        "example": "Mia",
                                        "maxLength": 80
                                    },
                                    "email": {
                                        "description": "E-Mail-Adresse des Benutzers. Muss eindeutig sein.",
                                        "type": "string",
                                        "format": "email",
                                        "example": "mia@test.de"
                                    },
                                    "password": {
                                        "description": "Passwort des Benutzers. Mindestens 8 Zeichen.",
                                        "type": "string",
                                        "format": "password",
                                        "example": "12345678",
                                        "minLength": 8
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Benutzer erfolgreich registriert.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Registrierung erfolgreich."
                                        },
                                        "user": {
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "example": 3
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "example": "Mia"
                                                },
                                                "email": {
                                                    "type": "string",
                                                    "example": "mia@test.de"
                                                },
                                                "role": {
                                                    "type": "string",
                                                    "example": "user"
                                                },
                                                "active": {
                                                    "type": "boolean",
                                                    "example": true
                                                },
                                                "created_at": {
                                                    "type": "string",
                                                    "example": "2026-06-03 18:30:00"
                                                },
                                                "updated_at": {
                                                    "type": "string",
                                                    "example": null,
                                                    "nullable": true
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Ungültige Eingabe.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Passwort muss mindestens 8 Zeichen lang sein."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "E-Mail-Adresse ist bereits registriert.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Diese E-Mail-Adresse ist bereits registriert."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate Limit überschritten.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Zu viele Anfragen. Bitte später erneut versuchen."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "500": {
                        "description": "Benutzer konnte nicht gespeichert werden.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Benutzer konnte nicht gespeichert werden."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/login": {
            "post": {
                "tags": [
                    "Auth"
                ],
                "summary": "Benutzer einloggen",
                "description": "Prüft E-Mail und Passwort. Bei Erfolg werden ein Access Token und ein Refresh Token zurückgegeben. Der Access Token wird für geschützte API-Endpunkte als Bearer Token verwendet.",
                "operationId": "loginUser",
                "requestBody": {
                    "description": "Login-Daten des Benutzers.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "email",
                                    "password"
                                ],
                                "properties": {
                                    "email": {
                                        "description": "E-Mail-Adresse des Benutzers.",
                                        "type": "string",
                                        "format": "email",
                                        "example": "mia@test.de"
                                    },
                                    "password": {
                                        "description": "Passwort des Benutzers.",
                                        "type": "string",
                                        "format": "password",
                                        "example": "12345678"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Login erfolgreich.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Login erfolgreich."
                                        },
                                        "token_type": {
                                            "type": "string",
                                            "example": "Bearer"
                                        },
                                        "expires_in": {
                                            "type": "integer",
                                            "example": 3600
                                        },
                                        "access_token": {
                                            "description": "Access Token für geschützte Endpunkte. In Swagger unter Authorize einfügen.",
                                            "type": "string",
                                            "example": "9f6c3c8f1d0f4dfd9e9f7f9fbdad8c0f4d7b6e5a1d3c2b1a0f9e8d7c6b5a4f3e"
                                        },
                                        "refresh_token": {
                                            "description": "Refresh Token zum Erzeugen eines neuen Access Tokens.",
                                            "type": "string",
                                            "example": "7b3e6a5f8d9c2b1a0f4e3d2c1b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0"
                                        },
                                        "user": {
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "example": 1
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "example": "Mia"
                                                },
                                                "email": {
                                                    "type": "string",
                                                    "example": "mia@test.de"
                                                },
                                                "role": {
                                                    "type": "string",
                                                    "example": "admin"
                                                },
                                                "active": {
                                                    "type": "boolean",
                                                    "example": true
                                                }
                                            },
                                            "type": "object"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Ungültiges JSON, ungültige E-Mail oder ungültiges Passwort.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Ungültige E-Mail-Adresse."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Login fehlgeschlagen.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Login fehlgeschlagen."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "423": {
                        "description": "Login temporär gesperrt wegen zu vieler Fehlversuche.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Zu viele fehlgeschlagene Login-Versuche. Bitte später erneut versuchen."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate Limit überschritten.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Zu viele Anfragen. Bitte später erneut versuchen."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/refresh": {
            "post": {
                "tags": [
                    "Auth"
                ],
                "summary": "Access Token erneuern",
                "description": "Erzeugt mit einem gültigen Refresh Token einen neuen Access Token. Der Refresh Token ist länger gültig als der Access Token.",
                "operationId": "refreshAccessToken",
                "requestBody": {
                    "description": "Refresh Token aus dem Login verwenden.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "refresh_token"
                                ],
                                "properties": {
                                    "refresh_token": {
                                        "description": "Refresh Token, der beim Login zurückgegeben wurde.",
                                        "type": "string",
                                        "example": "7b3e6a5f8d9c2b1a0f4e3d2c1b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Access Token erfolgreich erneuert.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Access Token erneuert."
                                        },
                                        "token_type": {
                                            "type": "string",
                                            "example": "Bearer"
                                        },
                                        "expires_in": {
                                            "type": "integer",
                                            "example": 3600
                                        },
                                        "access_token": {
                                            "type": "string",
                                            "example": "6a4f3e2d1c0b9a8f7e6d5c4b3a2f1e0d9c8b7a6f5e4d3c2b1a0f9e8d7c6b5a4f"
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "Ungültiges JSON.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Ungültiges JSON."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Refresh Token ungültig oder abgelaufen.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Refresh Token ungültig oder abgelaufen."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate Limit überschritten.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Zu viele Anfragen. Bitte später erneut versuchen."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/logout": {
            "post": {
                "tags": [
                    "Auth"
                ],
                "summary": "Benutzer ausloggen",
                "description": "Löscht den aktuellen Access Token. Danach kann dieser Token nicht mehr für geschützte Endpunkte verwendet werden.",
                "operationId": "logoutUser",
                "responses": {
                    "200": {
                        "description": "Logout erfolgreich.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": true
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Logout erfolgreich."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Token fehlt oder ungültig.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Token fehlt."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Rate Limit überschritten.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "properties": {
                                        "success": {
                                            "type": "boolean",
                                            "example": false
                                        },
                                        "message": {
                                            "type": "string",
                                            "example": "Zu viele Anfragen. Bitte später erneut versuchen."
                                        }
                                    },
                                    "type": "object"
                                }
                            }
                        }
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/tasks": {
            "get": {
                "tags": [
                    "Tasks"
                ],
                "summary": "Alle Aufgaben abrufen",
                "operationId": "3c6634b91286f175b804182e2f9995b7",
                "responses": {
                    "200": {
                        "description": "Aufgabenliste"
                    },
                    "401": {
                        "description": "Token fehlt oder ungültig"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            },
            "post": {
                "tags": [
                    "Tasks"
                ],
                "summary": "Neue Aufgabe erstellen",
                "operationId": "5a01e8a86f93d371708e53e51863d82e",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "title"
                                ],
                                "properties": {
                                    "title": {
                                        "type": "string",
                                        "example": "CRUD in React Native bauen"
                                    },
                                    "description": {
                                        "type": "string",
                                        "example": "Liste, Create, Update und Delete verbinden"
                                    },
                                    "status": {
                                        "type": "string",
                                        "example": "open",
                                        "enum": [
                                            "open",
                                            "done"
                                        ]
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Aufgabe erstellt"
                    },
                    "400": {
                        "description": "Ungültige Eingabe"
                    },
                    "401": {
                        "description": "Token fehlt oder ungültig"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/tasks/{id}": {
            "get": {
                "tags": [
                    "Tasks"
                ],
                "summary": "Einzelne Aufgabe abrufen",
                "operationId": "2af3c7c3a21ba68a5c083984eb40b5c0",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        },
                        "example": 1
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Aufgabe gefunden"
                    },
                    "404": {
                        "description": "Aufgabe nicht gefunden"
                    },
                    "401": {
                        "description": "Token fehlt oder ungültig"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            },
            "put": {
                "tags": [
                    "Tasks"
                ],
                "summary": "Aufgabe bearbeiten",
                "operationId": "78ac6f78ca3e9136ec87ec207764dd1a",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        },
                        "example": 1
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Aufgabe aktualisiert"
                    },
                    "400": {
                        "description": "Ungültige Eingabe"
                    },
                    "404": {
                        "description": "Aufgabe nicht gefunden"
                    },
                    "401": {
                        "description": "Token fehlt oder ungültig"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            },
            "delete": {
                "tags": [
                    "Tasks"
                ],
                "summary": "Aufgabe löschen",
                "operationId": "0334b16f00f165fc4da5c65ef4d9915f",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        },
                        "example": 1
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Aufgabe gelöscht"
                    },
                    "404": {
                        "description": "Aufgabe nicht gefunden"
                    },
                    "401": {
                        "description": "Token fehlt oder ungültig"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        }
    },
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "description": "Access Token aus dem Login verwenden. In Swagger nur den Token eintragen, ohne \"Bearer\".",
                "bearerFormat": "Token",
                "scheme": "bearer"
            }
        }
    },
    "tags": [
        {
            "name": "Auth",
            "description": "Login, Refresh Token und Logout"
        },
        {
            "name": "Tasks",
            "description": "Geschütztes Aufgaben-CRUD"
        }
    ]
}