Files

922 lines
22 KiB
YAML

openapi: 3.0.3
info:
title: Reference Board Viewer API
description: |
REST API for the Reference Board Viewer application - a web-based tool for artists
to collect, organize, and manipulate visual reference images.
version: 1.0.0
contact:
name: API Support
servers:
- url: http://localhost:8000/api/v1
description: Development server
- url: https://webref.example.com/api/v1
description: Production server
tags:
- name: Auth
description: Authentication and user management
- name: Boards
description: Board operations
- name: Images
description: Image upload and management
- name: Canvas
description: Canvas operations (positioning, transformations)
- name: Groups
description: Image grouping
- name: Sharing
description: Board sharing
security:
- BearerAuth: []
paths:
# ==================== Authentication ====================
/auth/register:
post:
tags: [Auth]
summary: Register new user
security: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [email, password]
properties:
email:
type: string
format: email
example: user@example.com
password:
type: string
minLength: 8
example: SecurePass123
responses:
'201':
description: User registered successfully
content:
application/json:
schema:
$ref: '#/components/schemas/UserResponse'
'400':
$ref: '#/components/responses/BadRequest'
'409':
$ref: '#/components/responses/Conflict'
/auth/login:
post:
tags: [Auth]
summary: Login user
security: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [email, password]
properties:
email:
type: string
format: email
password:
type: string
responses:
'200':
description: Login successful
content:
application/json:
schema:
type: object
properties:
access_token:
type: string
example: eyJhbGciOiJIUzI1NiIs...
token_type:
type: string
example: bearer
user:
$ref: '#/components/schemas/UserResponse'
'401':
$ref: '#/components/responses/Unauthorized'
/auth/me:
get:
tags: [Auth]
summary: Get current user
responses:
'200':
description: Current user details
content:
application/json:
schema:
$ref: '#/components/schemas/UserResponse'
'401':
$ref: '#/components/responses/Unauthorized'
# ==================== Boards ====================
/boards:
get:
tags: [Boards]
summary: List user's boards
parameters:
- name: limit
in: query
schema:
type: integer
default: 50
maximum: 100
- name: offset
in: query
schema:
type: integer
default: 0
responses:
'200':
description: List of boards
content:
application/json:
schema:
type: object
properties:
boards:
type: array
items:
$ref: '#/components/schemas/BoardSummary'
total:
type: integer
limit:
type: integer
offset:
type: integer
post:
tags: [Boards]
summary: Create new board
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [title]
properties:
title:
type: string
minLength: 1
maxLength: 255
example: Character Design References
description:
type: string
example: References for fantasy knight character
responses:
'201':
description: Board created
content:
application/json:
schema:
$ref: '#/components/schemas/BoardDetail'
'400':
$ref: '#/components/responses/BadRequest'
/boards/{board_id}:
parameters:
- $ref: '#/components/parameters/BoardId'
get:
tags: [Boards]
summary: Get board details
responses:
'200':
description: Board details with all images
content:
application/json:
schema:
$ref: '#/components/schemas/BoardDetail'
'404':
$ref: '#/components/responses/NotFound'
patch:
tags: [Boards]
summary: Update board
requestBody:
content:
application/json:
schema:
type: object
properties:
title:
type: string
description:
type: string
viewport_state:
$ref: '#/components/schemas/ViewportState'
responses:
'200':
description: Board updated
content:
application/json:
schema:
$ref: '#/components/schemas/BoardDetail'
'404':
$ref: '#/components/responses/NotFound'
delete:
tags: [Boards]
summary: Delete board
responses:
'204':
description: Board deleted
'404':
$ref: '#/components/responses/NotFound'
# ==================== Images ====================
/boards/{board_id}/images:
parameters:
- $ref: '#/components/parameters/BoardId'
post:
tags: [Images]
summary: Upload image(s) to board
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required: [files]
properties:
files:
type: array
items:
type: string
format: binary
maxItems: 50
position:
type: string
description: JSON string of default position
example: '{"x": 0, "y": 0}'
responses:
'201':
description: Images uploaded
content:
application/json:
schema:
type: object
properties:
images:
type: array
items:
$ref: '#/components/schemas/BoardImage'
'400':
$ref: '#/components/responses/BadRequest'
'413':
description: File too large
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/boards/{board_id}/images/{image_id}:
parameters:
- $ref: '#/components/parameters/BoardId'
- $ref: '#/components/parameters/ImageId'
patch:
tags: [Canvas]
summary: Update image position/transformations
requestBody:
content:
application/json:
schema:
type: object
properties:
position:
$ref: '#/components/schemas/Position'
transformations:
$ref: '#/components/schemas/Transformations'
z_order:
type: integer
group_id:
type: string
format: uuid
nullable: true
responses:
'200':
description: Image updated
content:
application/json:
schema:
$ref: '#/components/schemas/BoardImage'
'404':
$ref: '#/components/responses/NotFound'
delete:
tags: [Canvas]
summary: Remove image from board
responses:
'204':
description: Image removed from board
'404':
$ref: '#/components/responses/NotFound'
/boards/{board_id}/images/bulk:
parameters:
- $ref: '#/components/parameters/BoardId'
patch:
tags: [Canvas]
summary: Bulk update multiple images
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [image_ids, updates]
properties:
image_ids:
type: array
items:
type: string
format: uuid
updates:
type: object
properties:
position_delta:
type: object
properties:
dx:
type: number
dy:
type: number
transformations:
$ref: '#/components/schemas/Transformations'
z_order_delta:
type: integer
responses:
'200':
description: Images updated
content:
application/json:
schema:
type: object
properties:
updated_count:
type: integer
'400':
$ref: '#/components/responses/BadRequest'
# ==================== Groups ====================
/boards/{board_id}/groups:
parameters:
- $ref: '#/components/parameters/BoardId'
get:
tags: [Groups]
summary: List board groups
responses:
'200':
description: List of groups
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Group'
post:
tags: [Groups]
summary: Create group
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name, color, image_ids]
properties:
name:
type: string
example: Armor References
color:
type: string
pattern: '^#[0-9A-Fa-f]{6}$'
example: '#FF5733'
annotation:
type: string
example: Blue plate armor designs
image_ids:
type: array
items:
type: string
format: uuid
responses:
'201':
description: Group created
content:
application/json:
schema:
$ref: '#/components/schemas/Group'
'400':
$ref: '#/components/responses/BadRequest'
/boards/{board_id}/groups/{group_id}:
parameters:
- $ref: '#/components/parameters/BoardId'
- $ref: '#/components/parameters/GroupId'
patch:
tags: [Groups]
summary: Update group
requestBody:
content:
application/json:
schema:
type: object
properties:
name:
type: string
color:
type: string
annotation:
type: string
responses:
'200':
description: Group updated
content:
application/json:
schema:
$ref: '#/components/schemas/Group'
delete:
tags: [Groups]
summary: Delete group (ungroups images)
responses:
'204':
description: Group deleted
'404':
$ref: '#/components/responses/NotFound'
# ==================== Sharing ====================
/boards/{board_id}/share-links:
parameters:
- $ref: '#/components/parameters/BoardId'
get:
tags: [Sharing]
summary: List board share links
responses:
'200':
description: List of share links
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/ShareLink'
post:
tags: [Sharing]
summary: Create share link
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [permission_level]
properties:
permission_level:
type: string
enum: [view-only, view-comment]
expires_at:
type: string
format: date-time
nullable: true
responses:
'201':
description: Share link created
content:
application/json:
schema:
$ref: '#/components/schemas/ShareLink'
/boards/{board_id}/share-links/{link_id}:
parameters:
- $ref: '#/components/parameters/BoardId'
- name: link_id
in: path
required: true
schema:
type: string
format: uuid
delete:
tags: [Sharing]
summary: Revoke share link
responses:
'204':
description: Share link revoked
'404':
$ref: '#/components/responses/NotFound'
/shared/{token}:
parameters:
- name: token
in: path
required: true
schema:
type: string
get:
tags: [Sharing]
summary: Access shared board
security: []
responses:
'200':
description: Shared board details
content:
application/json:
schema:
type: object
properties:
board:
$ref: '#/components/schemas/BoardDetail'
permission_level:
type: string
enum: [view-only, view-comment]
'404':
description: Invalid or expired token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
# ==================== Export ====================
/boards/{board_id}/export:
parameters:
- $ref: '#/components/parameters/BoardId'
post:
tags: [Boards]
summary: Export board
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [format]
properties:
format:
type: string
enum: [zip, composite]
resolution:
type: integer
enum: [1, 2, 4]
default: 1
description: Resolution multiplier (for composite)
responses:
'200':
description: Export file
content:
application/zip:
schema:
type: string
format: binary
image/png:
schema:
type: string
format: binary
'400':
$ref: '#/components/responses/BadRequest'
# ==================== Image Library ====================
/library/images:
get:
tags: [Images]
summary: List user's image library
parameters:
- name: search
in: query
schema:
type: string
- name: limit
in: query
schema:
type: integer
default: 50
- name: offset
in: query
schema:
type: integer
default: 0
responses:
'200':
description: Image library
content:
application/json:
schema:
type: object
properties:
images:
type: array
items:
$ref: '#/components/schemas/ImageMetadata'
total:
type: integer
# ==================== Components ====================
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
parameters:
BoardId:
name: board_id
in: path
required: true
schema:
type: string
format: uuid
ImageId:
name: image_id
in: path
required: true
schema:
type: string
format: uuid
GroupId:
name: group_id
in: path
required: true
schema:
type: string
format: uuid
schemas:
UserResponse:
type: object
properties:
id:
type: string
format: uuid
email:
type: string
format: email
created_at:
type: string
format: date-time
BoardSummary:
type: object
properties:
id:
type: string
format: uuid
title:
type: string
description:
type: string
nullable: true
image_count:
type: integer
thumbnail_url:
type: string
nullable: true
created_at:
type: string
format: date-time
updated_at:
type: string
format: date-time
BoardDetail:
allOf:
- $ref: '#/components/schemas/BoardSummary'
- type: object
properties:
viewport_state:
$ref: '#/components/schemas/ViewportState'
images:
type: array
items:
$ref: '#/components/schemas/BoardImage'
groups:
type: array
items:
$ref: '#/components/schemas/Group'
ViewportState:
type: object
properties:
x:
type: number
example: 0
y:
type: number
example: 0
zoom:
type: number
minimum: 0.1
maximum: 5.0
example: 1.0
rotation:
type: number
minimum: 0
maximum: 360
example: 0
ImageMetadata:
type: object
properties:
id:
type: string
format: uuid
filename:
type: string
file_size:
type: integer
mime_type:
type: string
width:
type: integer
height:
type: integer
thumbnail_urls:
type: object
properties:
low:
type: string
medium:
type: string
high:
type: string
created_at:
type: string
format: date-time
reference_count:
type: integer
BoardImage:
allOf:
- $ref: '#/components/schemas/ImageMetadata'
- type: object
properties:
position:
$ref: '#/components/schemas/Position'
transformations:
$ref: '#/components/schemas/Transformations'
z_order:
type: integer
group_id:
type: string
format: uuid
nullable: true
Position:
type: object
properties:
x:
type: number
y:
type: number
Transformations:
type: object
properties:
scale:
type: number
minimum: 0.01
maximum: 10.0
default: 1.0
rotation:
type: number
minimum: 0
maximum: 360
default: 0
opacity:
type: number
minimum: 0.0
maximum: 1.0
default: 1.0
flipped_h:
type: boolean
default: false
flipped_v:
type: boolean
default: false
crop:
type: object
nullable: true
properties:
x:
type: number
y:
type: number
width:
type: number
height:
type: number
greyscale:
type: boolean
default: false
Group:
type: object
properties:
id:
type: string
format: uuid
name:
type: string
color:
type: string
pattern: '^#[0-9A-Fa-f]{6}$'
annotation:
type: string
nullable: true
member_count:
type: integer
created_at:
type: string
format: date-time
ShareLink:
type: object
properties:
id:
type: string
format: uuid
token:
type: string
permission_level:
type: string
enum: [view-only, view-comment]
url:
type: string
example: https://webref.example.com/shared/abc123...
created_at:
type: string
format: date-time
expires_at:
type: string
format: date-time
nullable: true
access_count:
type: integer
is_revoked:
type: boolean
Error:
type: object
properties:
error:
type: object
properties:
message:
type: string
code:
type: string
details:
type: object
nullable: true
responses:
BadRequest:
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthorized:
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Conflict:
description: Resource conflict
content:
application/json:
schema:
$ref: '#/components/schemas/Error'