# Dokumentacja projektów (/projekty) Każdy projekt ma tu własną część: opis, referencję API generowaną z kodu i instrukcję podłączenia agenta AI przez MCP. Wspólne przejazdy na festiwale w SzukamAndrzeja.pl. ## Dla agentów AI [#dla-agentów-ai] - [`/llms.txt`](/llms.txt) — spis wszystkich stron z linkami do wersji markdown. - [`/llms-full.txt`](/llms-full.txt) — cała dokumentacja w jednym pliku. - `/mcp` — serwer MCP z narzędziami `search` i `execute`. # Przejazdy (/projekty/przejazdy) Przejazdy łączą kierowców i pasażerów jadących na ten sam festiwal. API obsługuje przejazdy, rezerwacje miejsc, auta kierowców, czat, powiadomienia i opinie. ## Adres [#adres] ``` https://przejazdy.szukamandrzeja.pl ``` ## Logowanie [#logowanie] Operacje oznaczone kłódką wymagają sesji Better Auth, czyli ciasteczka `__Secure-better-auth.session_token` z logowania w SzukamAndrzeja.pl. Operacje publiczne (lista festiwali, wyszukiwarka, szczegóły przejazdu) działają bez logowania. ## Skąd jest ta referencja [#skąd-jest-ta-referencja] Referencja API powstaje z kontraktów oRPC w kodzie serwera. Plik `server/docs/openapi.json` pilnują dwa testy, więc opis nie rozjeżdża się z tym, co API naprawdę przyjmuje. ## Dla agentów AI [#dla-agentów-ai] - [`/projekty/przejazdy/llms.txt`](/projekty/przejazdy/llms.txt) — cały projekt w markdownie. - [Podłączenie przez MCP](/projekty/przejazdy/mcp) — wyszukiwanie i wywoływanie operacji. # MCP (/projekty/przejazdy/mcp) Serwer MCP pod `/mcp` ma dwa narzędzia, wspólne dla wszystkich projektów portalu: - **`search`** — znajduje operacje po opisie („zarezerwuj miejsce”, „moje auta”) i zwraca ich parametry oraz schemat treści żądania; - **`execute`** — wywołuje wybraną operację po `operationId`. Agent zawsze pyta najpierw `search`, a potem wywołuje `execute` z tym, co znalazł. ## Podłączenie [#podłączenie] ```bash claude mcp add --transport http dokumentacja https:///mcp ``` ## Działanie w imieniu użytkownika [#działanie-w-imieniu-użytkownika] MCP nie ma własnych uprawnień. Operacje publiczne działają od razu. Do operacji wymagających sesji klient podaje token sesji w nagłówku: ```bash claude mcp add --transport http dokumentacja https:///mcp \ --header "Authorization: Bearer " ``` MCP przepisuje token do ciasteczka sesji i wysyła żądanie wyłącznie pod adres API projektu. Agent może więc zrobić tylko to, co ten użytkownik w aplikacji. ## Czego MCP nie wywoła [#czego-mcp-nie-wywoła] Webhooki wewnętrzne, endpoint diagnostyczny oraz strumienie (czat przez WebSocket i powiadomienia przez SSE) są w referencji, ale `execute` ich nie obsługuje. # Health check (/projekty/przejazdy/api/health/getPrzejazdyHealth) ### Health check `GET /health` · operationId: `getPrzejazdyHealth` Health probe returning operational status of przejazdy server. **Odpowiedzi** - `200` OK # Informacje o buildzie (tylko IS_DEV) (/projekty/przejazdy/api/health/getPrzejazdyDebugInfo) ### Informacje o buildzie (tylko IS_DEV) `GET /debug-info` · operationId: `getPrzejazdyDebugInfo` Middleware zwraca 403, gdy IS_DEV !== 'true'; poza produkcją oddaje hash commita, gałąź i datę builda. **Odpowiedzi** - `200` Informacje o buildzie. - `403` Trasa dostępna tylko w środowisku deweloperskim. # List available rides (/projekty/przejazdy/api/rides/listPrzejazdyRides) ### List available rides `GET /api/rides` · operationId: `listPrzejazdyRides` Returns rides filtered by festival, date, route, and sorted as requested. **Parametry** - `cursor` (query): string - `limit` (query): integer - `festivalSlug` (query): string - `direction` (query): string - `status` (query): string - `departureCity` (query): string - `transportType` (query): string - `dateFrom` (query): string - `dateTo` (query): string - `hasAvailableSeats` (query): boolean - `maxCost` (query): number - `sortBy` (query): string **Odpowiedzi** - `200` OK # Create a new ride (/projekty/przejazdy/api/rides/createPrzejazdyRide) ### Create a new ride `POST /api/rides` · operationId: `createPrzejazdyRide` · wymaga sesji Creates a new ride for a festival. Author must be authenticated. **Treść żądania** (wymagana) ```json { "type": "object", "properties": { "festivalSlug": { "type": "string", "minLength": 1 }, "direction": { "enum": [ "to_festival", "from_festival", "both" ], "type": "string" }, "departureCity": { "type": "string", "minLength": 1 }, "departureAddress": { "type": "string" }, "departureLatitude": { "type": "number", "minimum": -90, "maximum": 90 }, "departureLongitude": { "type": "number", "minimum": -180, "maximum": 180 }, "departureDate": { "type": "string", "format": "date-time" }, "stops": { "type": "array", "items": { "type": "object", "properties": { "city": { "type": "string", "minLength": 1 }, "latitude": { "type": "number", "minimum": -90, "maximum": 90 }, "longitude": { "type": "number", "minimum": -180, "maximum": 180 }, "order": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": [ "city", "order" ] }, "default": [] }, "transportType": { "enum": [ "car", "train", "bus", "van", "other" ], "type": "string" }, "totalSeats": { "type": "integer", "minimum": 1, "maximum": 8 }, "costPerPerson": { "type": "number", "minimum": 0 }, "costDescription": { "type": "string", "maxLength": 200 }, "carId": { "type": "string" }, "description": { "type": "string", "maxLength": 500 }, "luggageSpace": { "enum": [ "small", "medium", "large", "none" ], "type": "string" }, "petsAllowed": { "type": "boolean", "default": false }, "smokingAllowed": { "type": "boolean", "default": false }, "femaleOnly": { "type": "boolean", "default": false } }, "required": [ "festivalSlug", "direction", "departureCity", "departureDate", "transportType", "totalSeats", "costPerPerson", "luggageSpace" ] } ``` **Odpowiedzi** - `201` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `429` Przekroczony limit żądań - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # List user rides (/projekty/przejazdy/api/rides/listPrzejazdyMyRides) ### List user rides `GET /api/rides/me` · operationId: `listPrzejazdyMyRides` · wymaga sesji Returns all rides created by the currently authenticated user. **Parametry** - `cursor` (query): string - `limit` (query): integer **Odpowiedzi** - `200` OK - `400` Niepoprawne dane wejściowe (domyślny kształt błędu walidatora) - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Get ride details (/projekty/przejazdy/api/rides/getPrzejazdyRide) ### Get ride details `GET /api/rides/{id}` · operationId: `getPrzejazdyRide` Returns full ride details including festival, car, author profile, and route stops. **Parametry** - `id` (path, wymagany): string **Odpowiedzi** - `200` OK # Update ride (/projekty/przejazdy/api/rides/updatePrzejazdyRide) ### Update ride `PUT /api/rides/{id}` · operationId: `updatePrzejazdyRide` · wymaga sesji Updates ride details. Only ride author can update. **Parametry** - `id` (path, wymagany): string **Treść żądania** (wymagana) ```json { "type": "object", "properties": { "festivalSlug": { "type": "string", "minLength": 1 }, "direction": { "enum": [ "to_festival", "from_festival", "both" ], "type": "string" }, "departureCity": { "type": "string", "minLength": 1 }, "departureAddress": { "type": "string" }, "departureLatitude": { "type": "number", "minimum": -90, "maximum": 90 }, "departureLongitude": { "type": "number", "minimum": -180, "maximum": 180 }, "departureDate": { "type": "string", "format": "date-time" }, "stops": { "type": "array", "items": { "type": "object", "properties": { "city": { "type": "string", "minLength": 1 }, "latitude": { "type": "number", "minimum": -90, "maximum": 90 }, "longitude": { "type": "number", "minimum": -180, "maximum": 180 }, "order": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": [ "city", "order" ] }, "default": [] }, "transportType": { "enum": [ "car", "train", "bus", "van", "other" ], "type": "string" }, "totalSeats": { "type": "integer", "minimum": 1, "maximum": 8 }, "costPerPerson": { "type": "number", "minimum": 0 }, "costDescription": { "type": "string", "maxLength": 200 }, "carId": { "type": "string" }, "description": { "type": "string", "maxLength": 500 }, "luggageSpace": { "enum": [ "small", "medium", "large", "none" ], "type": "string" }, "petsAllowed": { "type": "boolean", "default": false }, "smokingAllowed": { "type": "boolean", "default": false }, "femaleOnly": { "type": "boolean", "default": false }, "status": { "enum": [ "draft", "active", "full", "completed", "cancelled" ], "type": "string" } } } ``` **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Cancel ride (/projekty/przejazdy/api/rides/cancelPrzejazdyRide) ### Cancel ride `PATCH /api/rides/{id}/cancel` · operationId: `cancelPrzejazdyRide` · wymaga sesji Cancels an active ride and notifies passengers. **Parametry** - `id` (path, wymagany): string **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Search rides, festivals, and users (/projekty/przejazdy/api/search/searchPrzejazdyRides) ### Search rides, festivals, and users `GET /api/search` · operationId: `searchPrzejazdyRides` Global search matching query string against festival names, ride departure cities, and user names. **Parametry** - `q` (query): string - `limit` (query): integer **Odpowiedzi** - `200` OK # List festivals (/projekty/przejazdy/api/festivals/listPrzejazdyFestivals) ### List festivals `GET /api/festivals` · operationId: `listPrzejazdyFestivals` Retrieves a list of festivals, optionally filtered by active status. **Parametry** - `activeOnly` (query): string **Odpowiedzi** - `200` OK # Get festival details (/projekty/przejazdy/api/festivals/getPrzejazdyFestival) ### Get festival details `GET /api/festivals/{slug}` · operationId: `getPrzejazdyFestival` Returns festival details by slug. **Parametry** - `slug` (path, wymagany): string **Odpowiedzi** - `200` OK # Platform stats (/projekty/przejazdy/api/stats/getPrzejazdyStats) ### Platform stats `GET /api/stats` · operationId: `getPrzejazdyStats` Returns platform metrics (total rides, active festivals, passenger seats). **Odpowiedzi** - `200` OK # Get public user profile (/projekty/przejazdy/api/users/getPrzejazdyPublicUser) ### Get public user profile `GET /api/users/{id}/public` · operationId: `getPrzejazdyPublicUser` Returns public user profile, registered cars, and recent reviews. **Parametry** - `id` (path, wymagany): string **Odpowiedzi** - `200` OK # List my reservations (/projekty/przejazdy/api/reservations/reservationsMine) ### List my reservations `GET /api/reservations/me` · operationId: `reservationsMine` · wymaga sesji Returns reservations of the currently authenticated user with ride details and driver contact only when the reservation is accepted. **Parametry** - `status` (query): string - `cursor` (query): string - `limit` (query): integer **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # List reservations for a ride (/projekty/przejazdy/api/reservations/reservationsForRide) ### List reservations for a ride `GET /api/reservations/ride/{rideId}` · operationId: `reservationsForRide` · wymaga sesji Returns reservations for the given ride. Driver-only; passenger contact (phone) is exposed only for accepted reservations. **Parametry** - `rideId` (path, wymagany): string - `cursor` (query): string - `limit` (query): integer **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Create reservation request (/projekty/przejazdy/api/reservations/reservationsCreate) ### Create reservation request `POST /api/reservations` · operationId: `reservationsCreate` · wymaga sesji Passenger requests seats on an active ride; reserves seats atomically, opens a conversation and notifies the driver. **Treść żądania** (wymagana) ```json { "type": "object", "properties": { "rideId": { "type": "string", "minLength": 1 }, "seatsRequested": { "type": "integer", "minimum": 1, "maximum": 4 }, "message": { "type": "string", "maxLength": 300 } }, "required": [ "rideId", "seatsRequested" ] } ``` **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `429` Przekroczony limit żądań - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Respond to a reservation (/projekty/przejazdy/api/reservations/reservationsUpdateStatus) ### Respond to a reservation `PATCH /api/reservations/{id}/status` · operationId: `reservationsUpdateStatus` · wymaga sesji Driver accepts/rejects a pending reservation; passenger or driver cancels it. Seats are returned on reject/cancel. **Parametry** - `id` (path, wymagany): string **Treść żądania** (wymagana) ```json { "type": "object", "properties": { "action": { "enum": [ "accept", "reject", "cancel" ], "type": "string" } }, "required": [ "action" ] } ``` **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # List my cars (/projekty/przejazdy/api/cars/carsList) ### List my cars `GET /api/cars` · operationId: `carsList` · wymaga sesji Returns cars owned by the currently authenticated user (soft-deleted excluded). **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Create a car (/projekty/przejazdy/api/cars/carsCreate) ### Create a car `POST /api/cars` · operationId: `carsCreate` · wymaga sesji Adds a car to the authenticated user garage. **Treść żądania** (wymagana) ```json { "type": "object", "properties": { "brand": { "type": "string", "minLength": 1 }, "model": { "type": "string", "minLength": 1 }, "year": { "type": "integer", "minimum": 1950, "maximum": 9007199254740991 }, "color": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "photoUrl": { "anyOf": [ { "anyOf": [ { "type": "string", "format": "uri" }, { "const": "" } ] }, { "type": "null" } ] }, "doors": { "anyOf": [ { "type": "integer", "minimum": 2, "maximum": 10 }, { "type": "null" } ] }, "seats": { "anyOf": [ { "type": "integer", "minimum": 1, "maximum": 20 }, { "type": "null" } ] }, "bodyType": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "trunkCapacityLiters": { "anyOf": [ { "type": "integer", "minimum": 0, "maximum": 10000 }, { "type": "null" } ] } }, "required": [ "brand", "model", "year" ] } ``` **Odpowiedzi** - `201` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Get my car (/projekty/przejazdy/api/cars/carsGet) ### Get my car `GET /api/cars/{id}` · operationId: `carsGet` · wymaga sesji Returns a garaged car by id. Only the owner can read it. **Parametry** - `id` (path, wymagany): string **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Delete my car (/projekty/przejazdy/api/cars/carsDelete) ### Delete my car `DELETE /api/cars/{id}` · operationId: `carsDelete` · wymaga sesji Soft-deletes an owned car; refuses when the car is attached to active rides. **Parametry** - `id` (path, wymagany): string **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Update my car (/projekty/przejazdy/api/cars/carsUpdate) ### Update my car `PUT /api/cars/{id}` · operationId: `carsUpdate` · wymaga sesji Updates an owned car. Missing fields stay untouched; empty strings clear nullable fields. **Parametry** - `id` (path, wymagany): string **Treść żądania** (wymagana) ```json { "type": "object", "properties": { "brand": { "type": "string", "minLength": 1 }, "model": { "type": "string", "minLength": 1 }, "year": { "type": "integer", "minimum": 1950, "maximum": 9007199254740991 }, "color": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "photoUrl": { "anyOf": [ { "anyOf": [ { "type": "string", "format": "uri" }, { "const": "" } ] }, { "type": "null" } ] }, "doors": { "anyOf": [ { "type": "integer", "minimum": 2, "maximum": 10 }, { "type": "null" } ] }, "seats": { "anyOf": [ { "type": "integer", "minimum": 1, "maximum": 20 }, { "type": "null" } ] }, "bodyType": { "anyOf": [ { "type": "string" }, { "type": "null" } ] }, "trunkCapacityLiters": { "anyOf": [ { "type": "integer", "minimum": 0, "maximum": 10000 }, { "type": "null" } ] } } } ``` **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Create a review (/projekty/przejazdy/api/reviews/reviewsCreate) ### Create a review `POST /api/reviews` · operationId: `reviewsCreate` · wymaga sesji Leaves a review for a counterpart of a completed ride and refreshes their average rating. **Treść żądania** (wymagana) ```json { "type": "object", "properties": { "rideId": { "type": "string", "minLength": 1 }, "revieweeId": { "type": "string", "minLength": 1 }, "rating": { "type": "integer", "minimum": 1, "maximum": 5 }, "comment": { "type": "string", "maxLength": 500 } }, "required": [ "rideId", "revieweeId", "rating" ] } ``` **Odpowiedzi** - `201` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `429` Przekroczony limit żądań - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # List a user's reviews (/projekty/przejazdy/api/reviews/reviewsUser) ### List a user's reviews `GET /api/reviews/user/{userId}` · operationId: `reviewsUser` Returns public reviews received by the given user (no authentication required). **Parametry** - `userId` (path, wymagany): string **Odpowiedzi** - `200` OK # List user conversations (/projekty/przejazdy/api/chat/chatList) ### List user conversations `GET /api/chat` · operationId: `chatList` · wymaga sesji Returns conversations of the authenticated user with unread counts. **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Create conversation (/projekty/przejazdy/api/chat/chatCreate) ### Create conversation `POST /api/chat` · operationId: `chatCreate` · wymaga sesji Creates (or reuses) a conversation between the authenticated user and another ride participant. **Treść żądania** (wymagana) ```json { "type": "object", "properties": { "otherUserId": { "type": "string", "minLength": 1 }, "rideId": { "type": "string" } }, "required": [ "otherUserId" ] } ``` **Odpowiedzi** - `200` OK - `400` Niepoprawne dane wejściowe (domyślny kształt błędu walidatora) - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `429` Przekroczony limit żądań - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # List conversation messages (/projekty/przejazdy/api/chat/chatMessagesList) ### List conversation messages `GET /api/chat/{id}/messages` · operationId: `chatMessagesList` · wymaga sesji Returns messages of a conversation the user participates in; newest page first pagination ascending. **Parametry** - `id` (path, wymagany): string - `limit` (query): integer - `cursor` (query): string **Odpowiedzi** - `200` OK - `400` Niepoprawne dane wejściowe (domyślny kształt błędu walidatora) - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Send chat message (/projekty/przejazdy/api/chat/chatMessageCreate) ### Send chat message `POST /api/chat/{id}/messages` · operationId: `chatMessageCreate` · wymaga sesji Sends a message to a conversation the user participates in and notifies the recipient. **Parametry** - `id` (path, wymagany): string **Treść żądania** (wymagana) ```json { "type": "object", "properties": { "content": { "type": "string", "minLength": 1, "maxLength": 2000 } }, "required": [ "content" ] } ``` **Odpowiedzi** - `200` OK - `400` Niepoprawne dane wejściowe (domyślny kształt błędu walidatora) - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `429` Przekroczony limit żądań - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # WebSocket konwersacji (/projekty/przejazdy/api/chat/getPrzejazdyChatWs) ### WebSocket konwersacji `GET /api/chat/{id}/ws` · operationId: `getPrzejazdyChatWs` · wymaga sesji Przekazuje żądanie upgrade do Durable Object CHAT_DO (userId i conversationId jako parametry). Po sukcesie 101 Switching Protocols z ramkami JSON. **Parametry** - `id` (path, wymagany): string **Odpowiedzi** - `101` Przejście na protokół WebSocket (ramki JSON: message, messages_read). - `401` Brak sesji (unauthorized) - `403` Zalogowany użytkownik nie jest uczestnikiem konwersacji. - `404` Konwersacja nie istnieje. - `500` Błąd wewnętrzny. - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # List notifications (/projekty/przejazdy/api/notifications/notificationsList) ### List notifications `GET /api/notifications` · operationId: `notificationsList` · wymaga sesji Returns the latest 50 notifications of the authenticated user. **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Mark notification as read (/projekty/przejazdy/api/notifications/notificationMarkRead) ### Mark notification as read `PATCH /api/notifications/{id}/read` · operationId: `notificationMarkRead` · wymaga sesji Marks a single notification of the authenticated user as read. **Parametry** - `id` (path, wymagany): string **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Mark all notifications as read (/projekty/przejazdy/api/notifications/notificationsMarkAllRead) ### Mark all notifications as read `PATCH /api/notifications/read-all` · operationId: `notificationsMarkAllRead` · wymaga sesji Marks every unread notification of the authenticated user as read. **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Strumień SSE licznika nieprzeczytanych (/projekty/przejazdy/api/notifications/streamPrzejazdyNotifications) ### Strumień SSE licznika nieprzeczytanych `GET /api/notifications/stream` · operationId: `streamPrzejazdyNotifications` · wymaga sesji Server-Sent Events: co 10 s zdarzenie `notification` z { unreadCount }. **Odpowiedzi** - `200` Strumień SSE (event: notification). - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Get own profile (/projekty/przejazdy/api/profile/profileMeGet) ### Get own profile `GET /api/profile/me` · operationId: `profileMeGet` · wymaga sesji Returns the profile of the authenticated user and their cars. **Odpowiedzi** - `200` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Update own profile (/projekty/przejazdy/api/profile/profileMeUpdate) ### Update own profile `PATCH /api/profile/me` · operationId: `profileMeUpdate` · wymaga sesji Updates bio and phone of the authenticated user profile. **Treść żądania** (wymagana) ```json { "type": "object", "properties": { "bio": { "anyOf": [ { "type": "string", "maxLength": 300 }, { "type": "null" } ] }, "phone": { "anyOf": [ { "anyOf": [ { "type": "string", "pattern": "^(?:\\+?48[\\s-]?)?[1-9]\\d{2}[\\s-]?\\d{3}[\\s-]?\\d{3}$" }, { "const": "" } ] }, { "type": "null" } ] } } } ``` **Odpowiedzi** - `200` OK - `400` Niepoprawne dane wejściowe (domyślny kształt błędu walidatora) - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # Create report (/projekty/przejazdy/api/reports/reportCreate) ### Create report `POST /api/reports` · operationId: `reportCreate` · wymaga sesji Reports a ride or a user to the moderation queue. **Treść żądania** (wymagana) ```json { "type": "object", "properties": { "targetType": { "enum": [ "ride", "user" ], "type": "string" }, "targetId": { "type": "string", "minLength": 1 }, "reason": { "type": "string", "minLength": 5, "maxLength": 1000 } }, "required": [ "targetType", "targetId", "reason" ] } ``` **Odpowiedzi** - `201` OK - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `429` Przekroczony limit żądań - `503` Serwer logowania chwilowo niedostępny (auth_unavailable) # User deleted webhook (/projekty/przejazdy/api/webhooks/webhookUserDeleted) ### User deleted webhook `POST /api/webhooks/auth/user-deleted` · operationId: `webhookUserDeleted` Deletes every local record of a user removed from the auth service (bearer secret protected). **Treść żądania** (wymagana) ```json { "type": "object", "properties": { "userId": { "type": "string", "minLength": 1 } }, "required": [ "userId" ] } ``` **Odpowiedzi** - `200` OK - `429` Przekroczony limit żądań # Publiczny klucz VAPID (/projekty/przejazdy/api/push/getPrzejazdyVapidPublicKey) ### Publiczny klucz VAPID `GET /api/push/vapid-public-key` · operationId: `getPrzejazdyVapidPublicKey` Trasa publiczna; zwraca klucz publiczny albo 503, gdy push nie są skonfigurowane. **Odpowiedzi** - `200` Klucz publiczny VAPID. # Zapisz subskrypcję push (/projekty/przejazdy/api/push/createPrzejazdyPushSubscription) ### Zapisz subskrypcję push `POST /api/push/subscribe` · operationId: `createPrzejazdyPushSubscription` · wymaga sesji Zapisuje/odświeża subskrypcję Web Push dla endpointu; konflikt, gdy endpoint należy do innego użytkownika. **Treść żądania** (wymagana) ```json { "type": "object", "properties": { "endpoint": { "type": "string", "format": "uri" }, "keys": { "type": "object", "properties": { "p256dh": { "type": "string" }, "auth": { "type": "string" } }, "required": [ "p256dh", "auth" ] } }, "required": [ "endpoint", "keys" ] } ``` **Odpowiedzi** - `200` Zapisano subskrypcję. - `400` Niepoprawne dane wejściowe (domyślny kształt błędu walidatora) - `401` Brak sesji (unauthorized) - `403` Konto zablokowane - `409` Endpoint należy do innego użytkownika (conflict). # Usuń subskrypcję push (/projekty/przejazdy/api/push/deletePrzejazdyPushSubscription) ### Usuń subskrypcję push `DELETE /api/push/unsubscribe` · operationId: `deletePrzejazdyPushSubscription` · wymaga sesji Usuwa subskrypcję zalogowanego użytkownika dla podanego endpointu. **Treść żądania** (wymagana) ```json { "type": "object", "properties": { "endpoint": { "type": "string", "format": "uri" } }, "required": [ "endpoint" ] } ``` **Odpowiedzi** - `200` Usunięto subskrypcję. - `400` Niepoprawne dane wejściowe (domyślny kształt błędu walidatora) - `401` Brak sesji (unauthorized) - `403` Konto zablokowane