openapi: 3.1.0 info: title: Wallora Searcher API version: 0.1.0 description: Public API contract for Wallora Searcher. servers: - url: /api/v1 description: Local Next.js API route base paths: /auth/login: post: summary: Login app user with email and password requestBody: required: true content: application/json: schema: type: object required: - email - password properties: email: type: string format: email password: type: string responses: "200": description: App user token and profile. content: application/json: schema: $ref: "#/components/schemas/AuthResponse" "401": description: Invalid email or password, or the app user is disabled. /auth/register: post: summary: Register app user with email and password requestBody: required: true content: application/json: schema: type: object required: - email - password properties: email: type: string format: email password: type: string minLength: 8 displayName: type: - string - "null" responses: "200": description: App user token and profile. content: application/json: schema: $ref: "#/components/schemas/AuthResponse" "400": description: Invalid request or duplicate email. /gallery/collections: get: summary: List published photo collections description: Returns published photo collections with cover metadata. parameters: - name: page in: query schema: type: integer minimum: 1 default: 1 - name: pageSize in: query schema: type: integer minimum: 1 maximum: 50 default: 20 responses: "200": description: Paginated published collections. content: application/json: schema: type: object properties: ok: type: boolean data: type: array items: $ref: "#/components/schemas/PhotoCollection" pagination: $ref: "#/components/schemas/Pagination" /gallery/collections/{slug}: get: summary: Get a published photo collection description: Returns collection metadata and paginated picked photos in collection order. parameters: - name: slug in: path required: true schema: type: string - name: page in: query schema: type: integer minimum: 1 default: 1 - name: pageSize in: query schema: type: integer minimum: 1 maximum: 100 default: 24 responses: "200": description: Published collection with paginated photos. content: application/json: schema: type: object properties: ok: type: boolean data: type: object properties: collection: $ref: "#/components/schemas/PhotoCollection" photos: type: array items: $ref: "#/components/schemas/PickedGalleryPhoto" pagination: $ref: "#/components/schemas/Pagination" "404": description: Collection was not found or is not published. /gallery/photos: get: summary: List picked gallery photos description: Returns public picked photos for waterfall-style infinite scroll. If a Bearer JWT is provided, each photo includes current user's favorite state. security: - {} - bearerAuth: [] parameters: - name: page in: query schema: type: integer minimum: 1 default: 1 - name: pageSize in: query schema: type: integer minimum: 1 maximum: 100 default: 24 - name: colorFamily in: query schema: type: string enum: - all - black - blue - green - light - orange - purple - red - yellow responses: "200": description: Paginated picked photos. content: application/json: schema: type: object properties: ok: type: boolean data: type: array items: $ref: "#/components/schemas/PickedGalleryPhoto" pagination: $ref: "#/components/schemas/Pagination" /gallery/photos/{id}: get: summary: Get picked photo detail description: Returns one picked photo by id. If a Bearer JWT is provided, includes current user's favorite state. security: - {} - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": description: Picked photo detail. content: application/json: schema: type: object properties: ok: type: boolean data: $ref: "#/components/schemas/PickedGalleryPhoto" "404": description: Photo was not found or is not picked. post: summary: Favorite picked photo description: Adds the photo to the current user's favorites. security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": description: Favorited photo. content: application/json: schema: type: object properties: ok: type: boolean data: $ref: "#/components/schemas/FavoritePhoto" "401": description: Missing or invalid app user JWT. delete: summary: Unfavorite picked photo description: Removes the photo from the current user's favorites. security: - bearerAuth: [] parameters: - name: id in: path required: true schema: type: string format: uuid responses: "200": description: Favorite removed. "401": description: Missing or invalid app user JWT. /users/me: get: summary: Get current app user security: - bearerAuth: [] responses: "200": description: Current app user profile. content: application/json: schema: type: object properties: ok: type: boolean data: type: object properties: user: $ref: "#/components/schemas/AppUser" "401": description: Missing or invalid app user JWT. /users/me/favorites: get: summary: List current user's favorite photos security: - bearerAuth: [] parameters: - name: page in: query schema: type: integer minimum: 1 default: 1 - name: pageSize in: query schema: type: integer minimum: 1 maximum: 100 default: 24 responses: "200": description: Paginated favorite picked photos. content: application/json: schema: type: object properties: ok: type: boolean data: type: array items: $ref: "#/components/schemas/FavoritePhoto" pagination: $ref: "#/components/schemas/Pagination" "401": description: Missing or invalid app user JWT. post: summary: Add a picked photo to current user's favorites security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: - photoId properties: photoId: type: string format: uuid responses: "200": description: Favorited photo. content: application/json: schema: type: object properties: ok: type: boolean data: $ref: "#/components/schemas/FavoritePhoto" "401": description: Missing or invalid app user JWT. /users/me/favorites/{photoId}: delete: summary: Remove a photo from current user's favorites security: - bearerAuth: [] parameters: - name: photoId in: path required: true schema: type: string format: uuid responses: "200": description: Favorite removed. "401": description: Missing or invalid app user JWT. /users/me/settings: get: summary: Get current user's preferences security: - bearerAuth: [] responses: "200": description: User preferences and download preferences. content: application/json: schema: type: object properties: ok: type: boolean data: $ref: "#/components/schemas/UserSettings" "401": description: Missing or invalid app user JWT. patch: summary: Update current user's preferences security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object properties: preferences: type: object additionalProperties: true downloadPreferences: type: object additionalProperties: true responses: "200": description: Updated user settings. content: application/json: schema: type: object properties: ok: type: boolean data: $ref: "#/components/schemas/UserSettings" "401": description: Missing or invalid app user JWT. components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT schemas: AppUser: type: object properties: id: type: string format: uuid email: type: - string - "null" format: email displayName: type: - string - "null" avatarUrl: type: - string - "null" authProvider: type: string AuthResponse: type: object properties: ok: type: boolean data: type: object properties: token: type: string user: $ref: "#/components/schemas/AppUser" FavoritePhoto: allOf: - $ref: "#/components/schemas/PickedGalleryPhoto" - type: object properties: favoritedAt: type: - string - "null" format: date-time PhotoCollection: type: object properties: id: type: string format: uuid title: type: string slug: type: string description: type: - string - "null" coverPhoto: oneOf: - $ref: "#/components/schemas/PickedGalleryPhoto" - type: "null" coverUrl: type: - string - "null" photoCount: type: integer publishedAt: type: - string - "null" format: date-time PickedGalleryPhoto: type: object properties: id: type: string format: uuid unsplashId: type: string slug: type: - string - "null" description: type: - string - "null" altDescription: type: - string - "null" width: type: - integer - "null" height: type: - integer - "null" color: type: - string - "null" colorFamily: type: - string - "null" url: type: - string - "null" sourceUrl: type: - string - "null" user: type: object additionalProperties: true likes: type: - integer - "null" pickedAt: type: - string - "null" format: date-time isFavorited: type: boolean UserSettings: type: object properties: preferences: type: object additionalProperties: true downloadPreferences: type: object additionalProperties: true updatedAt: type: string format: date-time Pagination: type: object properties: page: type: integer pageSize: type: integer total: type: integer hasMore: type: boolean nextPage: type: - integer - "null"