585 lines
19 KiB
YAML
585 lines
19 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: PicPeak Admin API
|
|
version: 1.1.11
|
|
summary: High-level administrative endpoints for creating events, uploading photos, and resending gallery access emails.
|
|
description: |
|
|
This document describes the core administrative endpoints that power PicPeak automations.
|
|
It focuses on the three workflows requested by integrators:
|
|
|
|
1. Creating events with customer access credentials.
|
|
2. Uploading photos in bulk to an event gallery.
|
|
3. Resending the customer-facing gallery email.
|
|
|
|
The specification follows the latest [OpenAPI 3.1](https://spec.openapis.org/oas/v3.1.0) best practices
|
|
and is intended to be kept in sync with backend changes.
|
|
contact:
|
|
name: PicPeak Maintainers
|
|
url: https://github.com/the-luap/picpeak
|
|
servers:
|
|
- url: https://api.picpeak.example.com/api
|
|
description: Example production deployment
|
|
- url: http://localhost:3001/api
|
|
description: Local development
|
|
tags:
|
|
- name: Admin Events
|
|
description: Administrative endpoints for managing event galleries.
|
|
components:
|
|
securitySchemes:
|
|
CookieAuth:
|
|
type: apiKey
|
|
in: cookie
|
|
name: admin_token
|
|
description: >
|
|
Session cookie issued by the admin authentication flow. When present, the backend mirrors
|
|
it into the `Authorization` header automatically.
|
|
BearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
description: >
|
|
JSON Web Token created by the admin login endpoint. You can also pass the token explicitly
|
|
as `Authorization: Bearer <token>` instead of using the admin cookie.
|
|
parameters:
|
|
EventId:
|
|
name: eventId
|
|
in: path
|
|
description: Numeric identifier of the event.
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
example: 341
|
|
schemas:
|
|
ErrorResponse:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
description: Human readable error message.
|
|
details:
|
|
type: string
|
|
nullable: true
|
|
description: Additional context (when available).
|
|
required:
|
|
- error
|
|
example:
|
|
error: Invalid token
|
|
ValidationErrorItem:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
nullable: true
|
|
description: Validation error type reported by express-validator.
|
|
msg:
|
|
type: string
|
|
path:
|
|
type: string
|
|
description: Dot-delimited path to the invalid field.
|
|
value:
|
|
description: Value that failed validation.
|
|
location:
|
|
type: string
|
|
description: Location of the invalid value (always `body` for these endpoints).
|
|
required:
|
|
- msg
|
|
- path
|
|
- location
|
|
example:
|
|
type: field
|
|
msg: Event date must be a valid ISO 8601 date
|
|
path: event_date
|
|
value: 2025/05/01
|
|
location: body
|
|
ValidationErrorResponse:
|
|
type: object
|
|
properties:
|
|
errors:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ValidationErrorItem'
|
|
required:
|
|
- errors
|
|
example:
|
|
errors:
|
|
- type: field
|
|
msg: Customer email must be a valid address
|
|
path: customer_email
|
|
value: example@invalid
|
|
location: body
|
|
CreateEventRequest:
|
|
type: object
|
|
required:
|
|
- event_type
|
|
- event_name
|
|
- event_date
|
|
- customer_name
|
|
- customer_email
|
|
- admin_email
|
|
properties:
|
|
event_type:
|
|
type: string
|
|
description: Type of event. Controls default theme and copy in the UI.
|
|
enum: [wedding, birthday, corporate, other]
|
|
event_name:
|
|
type: string
|
|
minLength: 1
|
|
description: Display name for the gallery shown to end customers.
|
|
event_date:
|
|
type: string
|
|
format: date
|
|
description: Event date (YYYY-MM-DD). Used to calculate the default expiration.
|
|
customer_name:
|
|
type: string
|
|
minLength: 1
|
|
description: Name of the customer receiving gallery access.
|
|
customer_email:
|
|
type: string
|
|
format: email
|
|
description: Email address of the customer who will receive the gallery link.
|
|
admin_email:
|
|
type: string
|
|
format: email
|
|
description: Admin contact email included in notification messages.
|
|
require_password:
|
|
type: boolean
|
|
default: true
|
|
description: When true, the gallery requires `password`; when false a random placeholder is stored.
|
|
password:
|
|
type: string
|
|
minLength: 6
|
|
description: >
|
|
Gallery password issued to the customer. Required when `require_password` is `true`.
|
|
Left unset to auto-generate a placeholder when password protection is disabled.
|
|
expiration_days:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 365
|
|
default: 30
|
|
description: Number of days after the event date before the gallery expires.
|
|
welcome_message:
|
|
type: string
|
|
description: Optional welcome message displayed in the gallery.
|
|
color_theme:
|
|
type: string
|
|
nullable: true
|
|
description: Optional theme identifier or CSS color settings.
|
|
allow_user_uploads:
|
|
type: boolean
|
|
default: false
|
|
description: Allow gallery guests to upload their own photos.
|
|
upload_category_id:
|
|
type: integer
|
|
nullable: true
|
|
description: ID of the default category for user uploads.
|
|
allow_downloads:
|
|
type: boolean
|
|
default: true
|
|
description: Allow guests to download photos.
|
|
disable_right_click:
|
|
type: boolean
|
|
default: false
|
|
description: Disable right-click in the gallery view.
|
|
watermark_downloads:
|
|
type: boolean
|
|
default: false
|
|
description: Enable watermarking on downloaded images.
|
|
watermark_text:
|
|
type: string
|
|
nullable: true
|
|
description: Custom watermark text when `watermark_downloads` is true.
|
|
feedback_enabled:
|
|
type: boolean
|
|
default: false
|
|
description: Enable the feedback module for this gallery.
|
|
allow_ratings:
|
|
type: boolean
|
|
default: true
|
|
allow_likes:
|
|
type: boolean
|
|
default: true
|
|
allow_comments:
|
|
type: boolean
|
|
default: true
|
|
allow_favorites:
|
|
type: boolean
|
|
default: true
|
|
require_name_email:
|
|
type: boolean
|
|
default: false
|
|
description: Require guests to provide name and email when leaving feedback.
|
|
moderate_comments:
|
|
type: boolean
|
|
default: true
|
|
description: Hold guest comments for moderation.
|
|
show_feedback_to_guests:
|
|
type: boolean
|
|
default: true
|
|
description: Display aggregated feedback metrics back to guests.
|
|
example:
|
|
event_type: wedding
|
|
event_name: Emily & Jordan Celebration
|
|
event_date: 2025-06-07
|
|
customer_name: Emily Carter
|
|
customer_email: emily@example.com
|
|
admin_email: studio@example.com
|
|
require_password: true
|
|
password: Shutter123
|
|
expiration_days: 45
|
|
welcome_message: >
|
|
We loved capturing your day! Use the password below to view and download your photos.
|
|
allow_user_uploads: false
|
|
allow_downloads: true
|
|
feedback_enabled: true
|
|
allow_comments: true
|
|
show_feedback_to_guests: true
|
|
EventSummary:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
description: Database identifier of the newly created event.
|
|
slug:
|
|
type: string
|
|
description: Unique slug used to build the gallery URL.
|
|
event_name:
|
|
type: string
|
|
event_type:
|
|
type: string
|
|
enum: [wedding, birthday, corporate, other]
|
|
customer_name:
|
|
type: string
|
|
nullable: true
|
|
description: Name of the customer associated with the event.
|
|
customer_email:
|
|
type: string
|
|
format: email
|
|
nullable: true
|
|
description: Email address of the customer associated with the event.
|
|
require_password:
|
|
type: boolean
|
|
share_link:
|
|
type: string
|
|
description: Absolute or relative URL guests can use to reach the gallery.
|
|
expires_at:
|
|
type: string
|
|
format: date-time
|
|
description: ISO 8601 timestamp when the gallery expires.
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
description: ISO 8601 timestamp when the event was created.
|
|
required:
|
|
- id
|
|
- slug
|
|
- event_name
|
|
- event_type
|
|
- require_password
|
|
- share_link
|
|
- expires_at
|
|
- created_at
|
|
example:
|
|
id: 512
|
|
slug: wedding-emily-jordan-2025-06-07
|
|
event_name: Emily & Jordan Celebration
|
|
event_type: wedding
|
|
customer_name: Emily Carter
|
|
customer_email: emily@example.com
|
|
require_password: true
|
|
share_link: https://app.picpeak.io/gallery/wedding-emily-jordan-2025-06-07/2f3c8a4d90bb11ef9b2e0242ac120002
|
|
expires_at: 2025-07-22T00:00:00.000Z
|
|
created_at: 2025-05-01T14:32:45.000Z
|
|
UploadPhotosResponse:
|
|
type: object
|
|
properties:
|
|
message:
|
|
type: string
|
|
photos:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/UploadedPhotoSummary'
|
|
description: Metadata for each photo that was persisted successfully.
|
|
totalFiles:
|
|
type: integer
|
|
minimum: 0
|
|
description: Total number of files included in the request (valid + invalid).
|
|
successCount:
|
|
type: integer
|
|
minimum: 0
|
|
failureCount:
|
|
type: integer
|
|
minimum: 0
|
|
errors:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/UploadFailure'
|
|
description: Present when some files failed validation or processing.
|
|
required:
|
|
- message
|
|
- photos
|
|
- totalFiles
|
|
- successCount
|
|
- failureCount
|
|
example:
|
|
message: Uploaded 18 of 20 photos. 2 failed.
|
|
photos:
|
|
- id: 9821
|
|
filename: DSC_2031.jpg
|
|
size: 4812096
|
|
category_id: 2
|
|
- id: 9822
|
|
filename: DSC_2032.jpg
|
|
size: 5216743
|
|
category_id: 2
|
|
totalFiles: 20
|
|
successCount: 18
|
|
failureCount: 2
|
|
errors:
|
|
- filename: DSC_2020.raw
|
|
error: Only JPEG, PNG and WebP images are allowed
|
|
- filename: portrait.png
|
|
error: File is empty
|
|
UploadedPhotoSummary:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
filename:
|
|
type: string
|
|
size:
|
|
type: integer
|
|
description: File size in bytes.
|
|
category_id:
|
|
type: integer
|
|
nullable: true
|
|
required:
|
|
- id
|
|
- filename
|
|
- size
|
|
example:
|
|
id: 9821
|
|
filename: DSC_2031.jpg
|
|
size: 4812096
|
|
category_id: 2
|
|
UploadFailure:
|
|
type: object
|
|
properties:
|
|
filename:
|
|
type: string
|
|
error:
|
|
type: string
|
|
required:
|
|
- filename
|
|
- error
|
|
example:
|
|
filename: DSC_2031.gif
|
|
error: Only JPEG, PNG and WebP images are allowed
|
|
ResendEmailRequest:
|
|
type: object
|
|
properties:
|
|
password:
|
|
type: string
|
|
minLength: 1
|
|
description: >
|
|
Optional plain-text password to include in the email. When omitted a security notice
|
|
placeholder is inserted because the stored hash cannot be reversed.
|
|
example:
|
|
password: Shutter123
|
|
ResendEmailResponse:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
message:
|
|
type: string
|
|
required:
|
|
- success
|
|
- message
|
|
example:
|
|
success: true
|
|
message: Creation email has been queued for sending
|
|
paths:
|
|
/admin/events:
|
|
post:
|
|
tags: [Admin Events]
|
|
operationId: createAdminEvent
|
|
summary: Create a new event
|
|
description: >
|
|
Creates a new event, provisions storage folders, stores the gallery password, and queues
|
|
the initial gallery email for the customer. Requires admin authentication.
|
|
security:
|
|
- CookieAuth: []
|
|
- BearerAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateEventRequest'
|
|
examples:
|
|
weddingExample:
|
|
summary: Wedding with password protection
|
|
value:
|
|
event_type: wedding
|
|
event_name: Emily & Jordan Celebration
|
|
event_date: 2025-06-07
|
|
customer_name: Emily Carter
|
|
customer_email: emily@example.com
|
|
admin_email: studio@example.com
|
|
require_password: true
|
|
password: Shutter123
|
|
expiration_days: 45
|
|
welcome_message: >
|
|
We loved capturing your day! Use the password below to view and download your photos.
|
|
allow_user_uploads: false
|
|
allow_downloads: true
|
|
feedback_enabled: true
|
|
allow_comments: true
|
|
show_feedback_to_guests: true
|
|
responses:
|
|
'200':
|
|
description: Event created successfully.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EventSummary'
|
|
'400':
|
|
description: Validation failed. At least one field is invalid or missing.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ValidationErrorResponse'
|
|
'401':
|
|
description: Authentication required or token invalid.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'500':
|
|
description: Unexpected server error while creating the event.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
/admin/events/{eventId}/upload:
|
|
post:
|
|
tags: [Admin Events]
|
|
operationId: uploadEventPhotos
|
|
summary: Upload photos to an event gallery
|
|
description: |
|
|
Uploads one or more photos to the specified event. Files are validated, moved into the
|
|
event storage directory, and thumbnails are generated asynchronously.
|
|
|
|
The maximum number of files per upload is controlled via the `general_max_files_per_upload`
|
|
setting (default 500, capped at 2000). Files exceeding 50 MB are rejected.
|
|
security:
|
|
- CookieAuth: []
|
|
- BearerAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/EventId'
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
photos:
|
|
type: array
|
|
description: >
|
|
One or more image files (JPEG, PNG, WebP). Each file must be <= 50 MB.
|
|
items:
|
|
type: string
|
|
format: binary
|
|
category_id:
|
|
oneOf:
|
|
- type: integer
|
|
- type: string
|
|
description: >
|
|
Optional category assignment. Accepts numeric IDs or the string values `collage`
|
|
and `individual` for backward compatibility.
|
|
required:
|
|
- photos
|
|
encoding:
|
|
photos:
|
|
style: form
|
|
explode: false
|
|
responses:
|
|
'200':
|
|
description: Upload completed. Failed files (if any) are listed in the response.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UploadPhotosResponse'
|
|
'400':
|
|
description: Request failed validation (invalid files, too many files, etc.).
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'401':
|
|
description: Authentication required or token invalid.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: The referenced event does not exist.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'500':
|
|
description: Unexpected server error while processing uploads.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
/admin/events/{eventId}/resend-email:
|
|
post:
|
|
tags: [Admin Events]
|
|
operationId: resendEventEmail
|
|
summary: Resend the gallery access email to the customer
|
|
description: >
|
|
Queues the standard `gallery_created` email for the event's customer. Useful when resending
|
|
credentials to the customer or communicating an updated password. Requires admin authentication.
|
|
security:
|
|
- CookieAuth: []
|
|
- BearerAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/EventId'
|
|
requestBody:
|
|
required: false
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResendEmailRequest'
|
|
example:
|
|
password: NewSecurePassword!
|
|
responses:
|
|
'200':
|
|
description: Email successfully queued for delivery.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResendEmailResponse'
|
|
'401':
|
|
description: Authentication required or token invalid.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'404':
|
|
description: Event not found.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
'500':
|
|
description: Unexpected server error while queuing the email.
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|