openapi: 3.1.0 info: title: OpenAPI definition version: v0 servers: - url: http://localhost description: Generated server url tags: - name: Authentication description: Public Endpoints für Login und Registrierung - name: User Profile description: Profilverwaltung und Passwort-Reset - name: Admin IAM description: User-Verwaltung und Freigabe-Workflow paths: /api/users/me: get: tags: - User Profile summary: Eigenes Profil abrufen operationId: getOwnProfile responses: "200": description: OK content: '*/*': schema: $ref: "#/components/schemas/UserProfileResponse" put: tags: - User Profile summary: Profil aktualisieren operationId: updateOwnProfile requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateProfileRequest" required: true responses: "200": description: OK content: '*/*': schema: $ref: "#/components/schemas/UserProfileResponse" /api/users/me/password: put: tags: - User Profile summary: Passwort ändern operationId: changePassword requestBody: content: application/json: schema: $ref: "#/components/schemas/ChangePasswordRequest" required: true responses: "200": description: OK /api/users/me/email: put: tags: - User Profile summary: E-Mail ändern (mit erneuter Verifizierung) operationId: changeEmail requestBody: content: application/json: schema: $ref: "#/components/schemas/ChangeEmailRequest" required: true responses: "200": description: OK /api/tariffs/{tariffId}: put: tags: - user-tariff-controller operationId: updateUserTariff parameters: - name: tariffId in: path required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/UserTariffRequest" required: true responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/UserTariffResponse" delete: tags: - user-tariff-controller operationId: deleteUserTariff parameters: - name: tariffId in: path required: true schema: type: string format: uuid responses: "200": description: OK /api/notifications/{id}/read: put: tags: - notification-controller operationId: markAsRead parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": description: OK /api/notifications/read-all: put: tags: - notification-controller operationId: markAllAsRead responses: "200": description: OK /api/community/metering-points/{id}: put: tags: - metering-point-controller operationId: updateOwnMeteringPoint parameters: - name: id in: path required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/UpdateMeteringPointRequest" required: true responses: "200": description: OK content: '*/*': schema: $ref: "#/components/schemas/MeteringPointResponse" delete: tags: - metering-point-controller operationId: deleteOwnMeteringPoint parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": description: OK /api/community/admin/memberships/{id}/reject: put: tags: - membership-controller operationId: rejectMembership parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": description: OK /api/community/admin/memberships/{id}/approve: put: tags: - membership-controller operationId: approveMembership parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": description: OK /api/admin/energy-communities/{id}: get: tags: - energy-community-admin-controller operationId: getEnergyCommunityById parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/EnergyCommunityDto" put: tags: - energy-community-admin-controller operationId: updateEnergyCommunity parameters: - name: id in: path required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/EnergyCommunityDto" required: true responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/EnergyCommunityDto" delete: tags: - energy-community-admin-controller operationId: deleteEnergyCommunity parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": description: OK /api/admin/energy-communities/{communityId}/tariff: get: tags: - tariff-controller operationId: getCommunityTariff parameters: - name: communityId in: path required: true schema: type: string format: uuid responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/CommunityTariffResponse" put: tags: - tariff-controller operationId: createOrUpdateCommunityTariff parameters: - name: communityId in: path required: true schema: type: string format: uuid requestBody: content: application/json: schema: $ref: "#/components/schemas/CommunityTariffRequest" required: true responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/CommunityTariffResponse" /api/tariffs: post: tags: - user-tariff-controller operationId: createUserTariff requestBody: content: application/json: schema: $ref: "#/components/schemas/UserTariffRequest" required: true responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/UserTariffResponse" /api/tariffs/invites: post: tags: - tariff-invite-controller operationId: createInvite requestBody: content: application/json: schema: $ref: "#/components/schemas/TariffInviteRequest" required: true responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/TariffInviteResponse" /api/tariffs/invites/{inviteId}/accept: post: tags: - tariff-invite-controller operationId: acceptInvite parameters: - name: inviteId in: path required: true schema: type: string format: uuid responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/TariffInviteResponse" /api/community/metering-points: get: tags: - metering-point-controller operationId: getAllMeteringPoints responses: "200": description: OK content: '*/*': schema: type: array items: $ref: "#/components/schemas/MeteringPointResponse" post: tags: - metering-point-controller operationId: addOwnMeteringPoint requestBody: content: application/json: schema: $ref: "#/components/schemas/CreateMeteringPointRequest" required: true responses: "200": description: OK content: '*/*': schema: $ref: "#/components/schemas/MeteringPointResponse" /api/community/metering-data/upload: post: tags: - metering-data-controller operationId: uploadMeteringData requestBody: content: application/json: schema: $ref: "#/components/schemas/MeteringDataUploadRequest" required: true responses: "200": description: OK content: '*/*': schema: $ref: "#/components/schemas/MeteringDataUploadResponse" /api/community/metering-data/upload/xlsx: post: tags: - metering-data-controller operationId: uploadXlsx requestBody: content: multipart/form-data: schema: type: object properties: file: type: string format: binary required: - file responses: "200": description: OK content: '*/*': schema: $ref: "#/components/schemas/MeteringDataUploadResponse" /api/community/memberships/request: post: tags: - membership-controller operationId: requestMembership requestBody: content: application/json: schema: $ref: "#/components/schemas/MembershipRequest" required: true responses: "200": description: OK content: '*/*': schema: type: string format: uuid /api/auth/reset-password: post: tags: - User Profile summary: Passwort zurücksetzen operationId: resetPassword requestBody: content: application/json: schema: $ref: "#/components/schemas/ResetPasswordRequest" required: true responses: "200": description: OK /api/auth/register: post: tags: - Authentication summary: Registriert einen neuen User inkl. Zählpunkt description: Setzt den User auf Status PENDING und versendet eine Verifizierungs-E-Mail. operationId: register requestBody: content: application/json: schema: $ref: "#/components/schemas/RegistrationRequest" required: true responses: "200": description: OK /api/auth/login: post: tags: - Authentication summary: User Login description: "Gibt einen JWT zurück. Schlägt fehl, wenn Status noch PENDING\ \ ist." operationId: login requestBody: content: application/json: schema: $ref: "#/components/schemas/LoginRequest" required: true responses: "200": description: OK content: '*/*': schema: $ref: "#/components/schemas/AuthResponse" /api/auth/forgot-password: post: tags: - User Profile summary: Passwort-Reset anfordern operationId: forgotPassword requestBody: content: application/json: schema: $ref: "#/components/schemas/ForgotPasswordRequest" required: true responses: "200": description: OK /api/admin/users/{userId}/reject: post: tags: - Admin IAM summary: User ablehnen description: Lehnt den Antrag ab (z.B. weil Zählpunkt nicht ins Netz passt). operationId: rejectUser parameters: - name: userId in: path required: true schema: type: string format: uuid responses: "200": description: OK /api/admin/users/{userId}/approve: post: tags: - Admin IAM summary: User freigeben description: "Setzt enabled=true, status=APPROVED und triggert die finale EDA-Anmeldung." operationId: approveUser parameters: - name: userId in: path required: true schema: type: string format: uuid responses: "200": description: OK /api/admin/energy-communities: get: tags: - energy-community-admin-controller operationId: getAllEnergyCommunities responses: "200": description: Liste der wartenden Benutzer erfolgreich geladen content: application/json: schema: type: array items: $ref: "#/components/schemas/EnergyCommunityDto" post: tags: - energy-community-admin-controller operationId: createEnergyCommunity requestBody: content: application/json: schema: $ref: "#/components/schemas/EnergyCommunityDto" required: true responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/EnergyCommunityDto" /api/tariffs/invites/pending: get: tags: - tariff-invite-controller operationId: getPendingInvites responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/TariffInviteResponse" /api/tariffs/invites/community/{communityId}: get: tags: - tariff-invite-controller operationId: getInvitesForCommunity parameters: - name: communityId in: path required: true schema: type: string format: uuid responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/TariffInviteResponse" /api/tariffs/community/{communityId}: get: tags: - user-tariff-controller operationId: getUserTariffsForCommunity parameters: - name: communityId in: path required: true schema: type: string format: uuid responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/UserTariffResponse" /api/notifications: get: tags: - notification-controller operationId: getNotifications responses: "200": description: OK content: '*/*': schema: type: array items: $ref: "#/components/schemas/Notification" /api/notifications/unread: get: tags: - notification-controller operationId: getUnreadCount responses: "200": description: OK content: '*/*': schema: type: integer format: int64 /api/dashboard/user: get: tags: - dashboard-controller operationId: getUserDashboard responses: "200": description: OK content: '*/*': schema: $ref: "#/components/schemas/UserStats" /api/dashboard/admin: get: tags: - dashboard-controller operationId: getAdminDashboard responses: "200": description: OK content: '*/*': schema: $ref: "#/components/schemas/AdminStats" /api/community/metering-points/{id}/eligible-communities: get: tags: - membership-controller operationId: getEligibleCommunities parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": description: OK content: '*/*': schema: type: array items: $ref: "#/components/schemas/EligibleCommunityResponse" /api/community/metering-points/me: get: tags: - metering-point-controller operationId: getOwnMeteringPoints responses: "200": description: OK content: '*/*': schema: type: array items: $ref: "#/components/schemas/MeteringPointResponse" /api/community/metering-data/{meteringPointId}: get: tags: - metering-data-controller operationId: getMeteringData parameters: - name: meteringPointId in: path required: true schema: type: string format: uuid - name: from in: query required: true schema: type: string format: date-time - name: to in: query required: true schema: type: string format: date-time responses: "200": description: OK content: '*/*': schema: type: array items: $ref: "#/components/schemas/MeteringDataResponse" /api/community/metering-data/{meteringPointId}/by-type: get: tags: - metering-data-controller operationId: getMeteringDataByType parameters: - name: meteringPointId in: path required: true schema: type: string format: uuid - name: dataType in: query required: true schema: type: string enum: - CONSUMPTION - FEED_IN - SELF_CONSUMPTION - name: from in: query required: true schema: type: string format: date-time - name: to in: query required: true schema: type: string format: date-time responses: "200": description: OK content: '*/*': schema: type: array items: $ref: "#/components/schemas/MeteringDataResponse" /api/community/metering-data/upload/{uploadId}: get: tags: - metering-data-controller operationId: getUploadData parameters: - name: uploadId in: path required: true schema: type: string format: uuid responses: "200": description: OK content: '*/*': schema: type: array items: $ref: "#/components/schemas/MeteringDataResponse" /api/community/memberships/me: get: tags: - membership-controller operationId: getOwnMemberships responses: "200": description: OK content: '*/*': schema: type: array items: $ref: "#/components/schemas/MembershipResponse" /api/community/consumption/{meteringPointId}/dashboard: get: tags: - consumption-dashboard-controller operationId: getDashboard parameters: - name: meteringPointId in: path required: true schema: type: string format: uuid - name: from in: query required: true schema: type: string format: date-time - name: to in: query required: true schema: type: string format: date-time responses: "200": description: OK content: '*/*': schema: $ref: "#/components/schemas/ConsumptionDashboardResponse" /api/community/admin/memberships/pending: get: tags: - membership-controller operationId: getPendingMemberships responses: "200": description: OK content: '*/*': schema: type: array items: $ref: "#/components/schemas/PendingMembershipResponse" /api/auth/verify-email: get: tags: - Authentication operationId: verifyEmail parameters: - name: token in: query required: true schema: type: string responses: "200": description: OK /api/admin/users/pending: get: tags: - Admin IAM summary: Lädt alle wartenden User description: Zeigt User im Status PENDING inkl. der Ergebnisse des EDA-Netz-Checks. operationId: getPendingUsers responses: "200": description: Liste der wartenden Benutzer erfolgreich geladen content: application/json: schema: type: array items: $ref: "#/components/schemas/UserProfileResponse" components: schemas: UpdateProfileRequest: type: object description: Payload für die Profilaktualisierung properties: firstName: type: string description: Vorname example: Max minLength: 1 lastName: type: string description: Nachname example: Mustermann minLength: 1 organizationName: type: string description: "Nur bei juristischer Person: Firmen-, Vereins- oder Gemeindename" participantType: type: string description: Privatperson oder juristische Person enum: - PRIVATE - COMPANY example: PRIVATE required: - firstName - lastName - participantType UserProfileResponse: type: object description: Repräsentation eines Users für das Admin-Dashboard properties: id: type: string format: uuid participantType: type: string enum: - PRIVATE - COMPANY firstName: type: string lastName: type: string organizationName: type: string email: type: string status: type: string ChangePasswordRequest: type: object description: Payload für die Passwortänderung properties: currentPassword: type: string description: Aktuelles Passwort minLength: 1 newPassword: type: string description: Neues Passwort example: NeuesPasswort123! maxLength: 2147483647 minLength: 8 required: - currentPassword - newPassword ChangeEmailRequest: type: object description: Payload für die E-Mail-Änderung properties: newEmail: type: string format: email description: Neue E-Mail-Adresse example: neu@example.com minLength: 1 required: - newEmail UserTariffRequest: type: object properties: energyCommunityId: type: string format: uuid sourceMeteringPointId: type: string format: uuid targetMeteringPointId: type: string format: uuid pricePerKwhCents: type: number minimum: 0.0001 validFrom: type: string format: date validTo: type: string format: date required: - energyCommunityId - pricePerKwhCents - sourceMeteringPointId - targetMeteringPointId UserTariffResponse: type: object properties: id: type: string format: uuid energyCommunityId: type: string format: uuid sourceMeteringPointId: type: string format: uuid targetMeteringPointId: type: string format: uuid pricePerKwhCents: type: number validFrom: type: string format: date validTo: type: string format: date createdAt: type: string format: date-time UpdateMeteringPointRequest: type: object properties: type: type: string enum: - CONSUMER - PRODUCER - PROSUMER required: - type MeteringPointResponse: type: object properties: id: type: string format: uuid userId: type: string format: uuid atNumber: type: string type: type: string enum: - CONSUMER - PRODUCER - PROSUMER makoState: type: string enum: - NEW - WAITING_FOR_CONSENT - CONSENT_GRANTED - ACTIVE - REJECTED - ERROR gridOperatorId: type: string ownerEmail: type: string EnergyCommunityDto: type: object properties: id: type: string format: uuid edaEcId: type: string type: type: string enum: - EEG_LOKAL - EEG_REGIONAL - BEG name: type: string gridOperatorId: type: string substationId: type: string transformerId: type: string memberCount: type: integer format: int32 CommunityTariffRequest: type: object properties: maxPricePerKwhCents: type: number minimum: 0.0001 surchargePercent: type: number maximum: 100 minimum: 0 validFrom: type: string format: date validTo: type: string format: date required: - maxPricePerKwhCents - surchargePercent CommunityTariffResponse: type: object properties: id: type: string format: uuid energyCommunityId: type: string format: uuid maxPricePerKwhCents: type: number surchargePercent: type: number validFrom: type: string format: date validTo: type: string format: date createdAt: type: string format: date-time updatedAt: type: string format: date-time TariffInviteRequest: type: object properties: consumerUserId: type: string format: uuid energyCommunityId: type: string format: uuid note: type: string maxLength: 500 minLength: 0 required: - consumerUserId - energyCommunityId TariffInviteResponse: type: object properties: id: type: string format: uuid producerUserId: type: string format: uuid consumerUserId: type: string format: uuid energyCommunityId: type: string format: uuid code: type: string note: type: string status: type: string enum: - PENDING - ACCEPTED - EXPIRED expiresAt: type: string format: date-time acceptedAt: type: string format: date-time createdAt: type: string format: date-time CreateMeteringPointRequest: type: object properties: atNumber: type: string pattern: "^AT[0-9]{31}$" type: type: string enum: - CONSUMER - PRODUCER - PROSUMER required: - atNumber - type MeteringDataRecordDto: type: object properties: atNumber: type: string minLength: 1 pattern: "^AT[0-9]{31}$" dataType: type: string enum: - CONSUMPTION - FEED_IN - SELF_CONSUMPTION intervalStart: type: string format: date-time intervalEnd: type: string format: date-time kwh: type: number format: double minimum: 0 readingValue: type: number format: double required: - atNumber - dataType - intervalEnd - intervalStart - kwh MeteringDataUploadRequest: type: object properties: source: type: string enum: - EMAIL_XLSX - API - MANUAL fileName: type: string records: type: array items: $ref: "#/components/schemas/MeteringDataRecordDto" minItems: 1 required: - records - source MeteringDataUploadResponse: type: object properties: uploadId: type: string format: uuid status: type: string enum: - PENDING - PROCESSING - COMPLETED - FAILED recordCount: type: integer format: int32 validationErrors: type: array items: type: string MembershipRequest: type: object properties: meteringPointId: type: string format: uuid energyCommunityId: type: string format: uuid priorityLevel: type: integer format: int32 maximum: 5 minimum: 1 required: - energyCommunityId - meteringPointId - priorityLevel ResetPasswordRequest: type: object description: Payload für Passwort zurücksetzen properties: token: type: string description: Reset-Token minLength: 1 newPassword: type: string description: Neues Passwort example: NeuesPasswort123! maxLength: 2147483647 minLength: 8 required: - newPassword - token RegistrationRequest: type: object description: Payload für die Registrierung eines neuen Users properties: participantType: type: string description: Privatperson oder juristische Person (Firma/Verein/Gemeinde) enum: - PRIVATE - COMPANY example: PRIVATE firstName: type: string description: "Vorname (bei juristischer Person: Vorname der Ansprechperson)" example: Max minLength: 1 lastName: type: string description: "Nachname (bei juristischer Person: Nachname der Ansprechperson)" example: Mustermann minLength: 1 organizationName: type: string description: "Nur bei juristischer Person: Firmen-, Vereins- oder Gemeindename" example: Musterverein email: type: string format: email example: max@example.com minLength: 1 password: type: string example: SecurePass123! maxLength: 2147483647 minLength: 8 required: - email - firstName - lastName - participantType - password LoginRequest: type: object description: Payload für den Login properties: email: type: string format: email example: max@example.com minLength: 1 password: type: string example: SecurePass123! minLength: 1 required: - email - password AuthResponse: type: object description: Antwort nach erfolgreichem Login properties: token: type: string description: JWT Bearer Token status: type: string description: Status des Users example: PENDING role: type: string description: Rolle des Users example: USER ForgotPasswordRequest: type: object description: Payload für Passwort-Reset anfordern properties: email: type: string format: email description: E-Mail-Adresse example: max@example.com minLength: 1 required: - email Notification: type: object properties: id: type: string format: uuid userId: type: string format: uuid title: type: string message: type: string type: type: string enum: - INFO - SUCCESS - WARNING - ERROR read: type: boolean createdAt: type: string format: date-time UserStats: type: object properties: totalMeteringPoints: type: integer format: int64 activeMemberships: type: integer format: int64 pendingMemberships: type: integer format: int64 AdminStats: type: object properties: totalCommunities: type: integer format: int64 pendingUsers: type: integer format: int64 pendingMemberships: type: integer format: int64 totalActiveMemberships: type: integer format: int64 EligibleCommunityResponse: type: object properties: id: type: string format: uuid name: type: string type: type: string enum: - EEG_LOKAL - EEG_REGIONAL - BEG edaEcId: type: string MeteringDataResponse: type: object properties: id: type: string format: uuid meteringPointId: type: string format: uuid atNumber: type: string dataType: type: string enum: - CONSUMPTION - FEED_IN - SELF_CONSUMPTION intervalStart: type: string format: date-time intervalEnd: type: string format: date-time kwh: type: number format: double readingValue: type: number format: double source: type: string enum: - EMAIL_XLSX - API - MANUAL MembershipResponse: type: object properties: id: type: string format: uuid meteringPointId: type: string format: uuid atNumber: type: string energyCommunityId: type: string format: uuid communityName: type: string priorityLevel: type: integer format: int32 status: type: string validFrom: type: string format: date validTo: type: string format: date ConsumptionDashboardResponse: type: object properties: meteringPointId: type: string format: uuid atNumber: type: string energyCommunityId: type: string format: uuid communityName: type: string from: type: string format: date-time to: type: string format: date-time granularity: type: string data: type: array items: $ref: "#/components/schemas/IntervalData" summary: $ref: "#/components/schemas/Summary" IntervalData: type: object properties: timestamp: type: string format: date-time consumptionKwh: type: number format: double communityFeedInKwh: type: number format: double coveredKwh: type: number format: double coveragePercent: type: number format: double Summary: type: object properties: totalConsumptionKwh: type: number format: double totalCoveredKwh: type: number format: double totalCommunityFeedInKwh: type: number format: double averageCoveragePercent: type: number format: double PendingMembershipResponse: type: object properties: id: type: string format: uuid userEmail: type: string firstName: type: string lastName: type: string atNumber: type: string communityName: type: string priorityLevel: type: integer format: int32 status: type: string