openapi: 3.0.3 info: title: PicPeak API version: v1 description: >- Public REST API for PicPeak — create gallery events, upload photos, fetch share links. Authenticate with a Bearer token issued via the admin **Settings → API Tokens** tab. servers: - url: /api/v1 description: Same-origin (production) components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: pp_live_* description: >- Long-lived API token. Issue via Settings → API Tokens. Token format: `pp_live_`. Scopes: `read`, `write`, `admin`. schemas: EventSummary: type: object properties: id: type: integer slug: type: string event_name: type: string event_type: type: string event_date: type: string format: date nullable: true expires_at: type: string format: date-time nullable: true is_active: type: boolean is_archived: type: boolean is_draft: type: boolean created_at: type: string format: date-time security: - bearerAuth: [] paths: /events: post: tags: - Events summary: Create a gallery event description: Returns the new event's id, slug, and absolute share URL. security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: - event_name - event_type properties: event_name: type: string event_type: type: string enum: - wedding - birthday - corporate - other - family event_date: type: string format: date nullable: true customer_name: type: string nullable: true customer_email: type: string format: email nullable: true customer_phone: type: string nullable: true description: Only persisted when the global phone-field setting is enabled. admin_email: type: string format: email nullable: true require_password: type: boolean default: true password: type: string nullable: true description: Required when require_password is true. expires_at: type: string format: date-time nullable: true responses: '201': description: Event created content: application/json: schema: type: object properties: id: type: integer slug: type: string share_url: type: string format: uri share_token: type: string '400': description: Validation error '401': description: Missing/invalid token '403': description: Token lacks admin scope get: tags: - Events summary: List gallery events (paginated) security: - bearerAuth: [] parameters: - in: query name: page schema: type: integer minimum: 1 default: 1 - in: query name: limit schema: type: integer minimum: 1 maximum: 100 default: 25 responses: '200': description: Paginated list content: application/json: schema: type: object properties: events: type: array items: $ref: '#/components/schemas/EventSummary' pagination: type: object properties: page: type: integer limit: type: integer total: type: integer /events/{id}: get: tags: - Events summary: Get a single event security: - bearerAuth: [] parameters: - in: path name: id required: true schema: type: integer responses: '200': description: Event details '404': description: Not found /events/{id}/photos: post: tags: - Photos summary: Upload a single photo to an event security: - bearerAuth: [] parameters: - in: path name: id required: true schema: type: integer requestBody: required: true content: multipart/form-data: schema: type: object required: - photo properties: photo: type: string format: binary responses: '201': description: Photo uploaded content: application/json: schema: type: object properties: id: type: integer filename: type: string path: type: string thumbnail_path: type: string nullable: true size_bytes: type: integer '400': description: No file or invalid type '404': description: Event not found /events/{id}/share-link: get: tags: - Events summary: Get the absolute share URL for an event security: - bearerAuth: [] parameters: - in: path name: id required: true schema: type: integer responses: '200': description: Share URL content: application/json: schema: type: object properties: slug: type: string share_token: type: string share_url: type: string format: uri '404': description: Not found tags: []