mirror of
https://github.com/Dvorinka/excalidraw-full.git
synced 2026-06-03 22:02:57 +00:00
696 lines
21 KiB
YAML
696 lines
21 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: Excalidraw Full Workspace API
|
|
version: 0.1.0
|
|
description: Backend-owned workspace API for auth, teams, drawings, folders, projects, templates, revisions, and activity.
|
|
servers:
|
|
- url: /api
|
|
security:
|
|
- cookieSession: []
|
|
components:
|
|
securitySchemes:
|
|
cookieSession:
|
|
type: apiKey
|
|
in: cookie
|
|
name: excalidraw_session
|
|
schemas:
|
|
Error:
|
|
type: object
|
|
required: [error]
|
|
properties:
|
|
error:
|
|
type: string
|
|
User:
|
|
type: object
|
|
required: [id, name, username, email, locale, timezone, created_at, updated_at]
|
|
properties:
|
|
id: { type: string }
|
|
name: { type: string }
|
|
username: { type: string }
|
|
email: { type: string, format: email }
|
|
avatar_url: { type: [string, "null"] }
|
|
locale: { type: string }
|
|
timezone: { type: string }
|
|
created_at: { type: string, format: date-time }
|
|
updated_at: { type: string, format: date-time }
|
|
Session:
|
|
type: object
|
|
required: [id, user_id, expires_at, created_at]
|
|
properties:
|
|
id: { type: string }
|
|
user_id: { type: string }
|
|
expires_at: { type: string, format: date-time }
|
|
created_at: { type: string, format: date-time }
|
|
Team:
|
|
type: object
|
|
required: [id, name, slug, owner_user_id, plan_type, created_at, updated_at]
|
|
properties:
|
|
id: { type: string }
|
|
name: { type: string }
|
|
slug: { type: string }
|
|
owner_user_id: { type: string }
|
|
plan_type: { type: string, enum: [free, pro] }
|
|
created_at: { type: string, format: date-time }
|
|
updated_at: { type: string, format: date-time }
|
|
TeamMembership:
|
|
type: object
|
|
required: [id, team_id, user_id, role, joined_at]
|
|
properties:
|
|
id: { type: string }
|
|
team_id: { type: string }
|
|
user_id: { type: string }
|
|
role: { type: string, enum: [owner, admin, editor, viewer] }
|
|
joined_at: { type: string, format: date-time }
|
|
user:
|
|
$ref: "#/components/schemas/User"
|
|
Drawing:
|
|
type: object
|
|
required: [id, team_id, title, owner_user_id, visibility, is_archived, created_at, updated_at]
|
|
properties:
|
|
id: { type: string }
|
|
team_id: { type: string }
|
|
folder_id: { type: [string, "null"] }
|
|
project_id: { type: [string, "null"] }
|
|
slug: { type: [string, "null"] }
|
|
title: { type: string }
|
|
description: { type: [string, "null"] }
|
|
owner_user_id: { type: string }
|
|
latest_revision_id: { type: [string, "null"] }
|
|
visibility: { type: string, enum: [private, team, restricted, public-link] }
|
|
is_archived: { type: boolean }
|
|
thumbnail_asset_id: { type: [string, "null"] }
|
|
created_at: { type: string, format: date-time }
|
|
updated_at: { type: string, format: date-time }
|
|
deleted_at: { type: [string, "null"], format: date-time }
|
|
owner:
|
|
$ref: "#/components/schemas/User"
|
|
DrawingRevision:
|
|
type: object
|
|
required: [id, drawing_id, revision_number, snapshot_path, snapshot_size, content_hash, created_by, created_at]
|
|
properties:
|
|
id: { type: string }
|
|
drawing_id: { type: string }
|
|
revision_number: { type: integer }
|
|
snapshot_path: { type: string }
|
|
snapshot_size: { type: integer, format: int64 }
|
|
content_hash: { type: string }
|
|
created_by: { type: string }
|
|
created_at: { type: string, format: date-time }
|
|
change_summary: { type: [string, "null"] }
|
|
snapshot: {}
|
|
Template:
|
|
type: object
|
|
required: [id, scope, type, name, snapshot_path, metadata_json, created_by, created_at, updated_at]
|
|
properties:
|
|
id: { type: string }
|
|
team_id: { type: [string, "null"] }
|
|
scope: { type: string, enum: [system, team, personal] }
|
|
type: { type: string }
|
|
name: { type: string }
|
|
description: { type: [string, "null"] }
|
|
snapshot_path: { type: string }
|
|
metadata_json: { type: object, additionalProperties: true }
|
|
created_by: { type: string }
|
|
created_at: { type: string, format: date-time }
|
|
updated_at: { type: string, format: date-time }
|
|
ActivityEvent:
|
|
type: object
|
|
required: [id, resource_type, resource_id, event_type, metadata_json, created_at]
|
|
properties:
|
|
id: { type: string }
|
|
actor_user_id: { type: [string, "null"] }
|
|
team_id: { type: [string, "null"] }
|
|
resource_type: { type: string }
|
|
resource_id: { type: string }
|
|
event_type: { type: string }
|
|
metadata_json: { type: object, additionalProperties: true }
|
|
created_at: { type: string, format: date-time }
|
|
actor:
|
|
$ref: "#/components/schemas/User"
|
|
TeamInvite:
|
|
type: object
|
|
required: [id, team_id, email, role, invited_by, expires_at, created_at]
|
|
properties:
|
|
id: { type: string }
|
|
team_id: { type: string }
|
|
email: { type: string, format: email }
|
|
role: { type: string, enum: [admin, editor, viewer] }
|
|
invited_by: { type: string }
|
|
expires_at: { type: string, format: date-time }
|
|
created_at: { type: string, format: date-time }
|
|
PermissionGrant:
|
|
type: object
|
|
required: [id, resource_type, resource_id, subject_type, subject_id, permission, created_at]
|
|
properties:
|
|
id: { type: string }
|
|
resource_type: { type: string }
|
|
resource_id: { type: string }
|
|
subject_type: { type: string, enum: [user, team, link] }
|
|
subject_id: { type: string }
|
|
permission: { type: string, enum: [view, comment, edit, manage, share, invite] }
|
|
inherited_from: { type: [string, "null"] }
|
|
created_at: { type: string, format: date-time }
|
|
ShareLink:
|
|
type: object
|
|
required: [id, resource_type, resource_id, permission, created_by, created_at]
|
|
properties:
|
|
id: { type: string }
|
|
resource_type: { type: string, enum: [drawing, folder, project] }
|
|
resource_id: { type: string }
|
|
permission: { type: string, enum: [view, comment, edit] }
|
|
expires_at: { type: [string, "null"], format: date-time }
|
|
created_by: { type: string }
|
|
revoked_at: { type: [string, "null"], format: date-time }
|
|
created_at: { type: string, format: date-time }
|
|
DrawingAsset:
|
|
type: object
|
|
required: [id, drawing_id, kind, path, mime_type, size, uploaded_by, created_at]
|
|
properties:
|
|
id: { type: string }
|
|
drawing_id: { type: string }
|
|
kind: { type: string, enum: [image, export, attachment, thumbnail] }
|
|
path: { type: string }
|
|
mime_type: { type: string }
|
|
size: { type: integer, format: int64 }
|
|
width: { type: [integer, "null"] }
|
|
height: { type: [integer, "null"] }
|
|
uploaded_by: { type: string }
|
|
created_at: { type: string, format: date-time }
|
|
Embed:
|
|
type: object
|
|
required: [id, drawing_id, source_url, canonical_url, provider, embed_type, created_by, created_at]
|
|
properties:
|
|
id: { type: string }
|
|
drawing_id: { type: string }
|
|
source_url: { type: string, format: uri }
|
|
canonical_url: { type: string, format: uri }
|
|
provider: { type: string }
|
|
embed_type: { type: string, enum: [link, iframe, provider] }
|
|
title: { type: [string, "null"] }
|
|
preview_asset_id: { type: [string, "null"] }
|
|
safe_embed_html: { type: [string, "null"] }
|
|
created_by: { type: string }
|
|
created_at: { type: string, format: date-time }
|
|
LinkReference:
|
|
type: object
|
|
required: [id, source_resource_type, source_resource_id, target_resource_type, target_resource_id, created_by, created_at]
|
|
properties:
|
|
id: { type: string }
|
|
source_resource_type: { type: string }
|
|
source_resource_id: { type: string }
|
|
target_resource_type: { type: string, enum: [drawing, folder, project, embed] }
|
|
target_resource_id: { type: string }
|
|
label: { type: [string, "null"] }
|
|
created_by: { type: string }
|
|
created_at: { type: string, format: date-time }
|
|
WorkspaceStats:
|
|
type: object
|
|
required: [teams, members, projects, folders, drawings, templates, revisions, assets, storage_bytes]
|
|
properties:
|
|
teams: { type: integer }
|
|
members: { type: integer }
|
|
projects: { type: integer }
|
|
folders: { type: integer }
|
|
drawings: { type: integer }
|
|
templates: { type: integer }
|
|
revisions: { type: integer }
|
|
assets: { type: integer }
|
|
storage_bytes: { type: integer, format: int64 }
|
|
Project:
|
|
type: object
|
|
required: [id, team_id, name, slug, created_by, created_at, updated_at]
|
|
properties:
|
|
id: { type: string }
|
|
team_id: { type: string }
|
|
name: { type: string }
|
|
slug: { type: string }
|
|
description: { type: [string, "null"] }
|
|
created_by: { type: string }
|
|
created_at: { type: string, format: date-time }
|
|
updated_at: { type: string, format: date-time }
|
|
Folder:
|
|
type: object
|
|
required: [id, team_id, name, slug, path_cache, visibility, created_by, created_at, updated_at]
|
|
properties:
|
|
id: { type: string }
|
|
team_id: { type: string }
|
|
project_id: { type: [string, "null"] }
|
|
parent_folder_id: { type: [string, "null"] }
|
|
name: { type: string }
|
|
slug: { type: string }
|
|
path_cache: { type: string }
|
|
visibility: { type: string, enum: [private, team] }
|
|
created_by: { type: string }
|
|
created_at: { type: string, format: date-time }
|
|
updated_at: { type: string, format: date-time }
|
|
paths:
|
|
/health:
|
|
get:
|
|
security: []
|
|
summary: Health check
|
|
responses:
|
|
"200":
|
|
description: Backend healthy
|
|
"503":
|
|
description: Backend unhealthy
|
|
/auth/signup:
|
|
post:
|
|
security: []
|
|
summary: Create password account
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [name, email, password]
|
|
properties:
|
|
name: { type: string, minLength: 1, maxLength: 120 }
|
|
email: { type: string, format: email }
|
|
password: { type: string, minLength: 8, maxLength: 128 }
|
|
responses:
|
|
"201":
|
|
description: Signed up
|
|
"409":
|
|
description: Email already exists
|
|
/auth/login:
|
|
post:
|
|
security: []
|
|
summary: Login 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: Logged in
|
|
"401":
|
|
description: Invalid credentials
|
|
/auth/logout:
|
|
post:
|
|
summary: Revoke current session
|
|
responses:
|
|
"200":
|
|
description: Logged out
|
|
/auth/me:
|
|
get:
|
|
summary: Current user
|
|
responses:
|
|
"200":
|
|
description: Current user
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/User"
|
|
/teams:
|
|
get:
|
|
summary: List accessible teams
|
|
responses:
|
|
"200":
|
|
description: Teams
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Team"
|
|
post:
|
|
summary: Create team
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [name]
|
|
properties:
|
|
name: { type: string }
|
|
slug: { type: string }
|
|
responses:
|
|
"201":
|
|
description: Created team
|
|
/teams/{teamID}/members:
|
|
get:
|
|
summary: List team members
|
|
parameters:
|
|
- in: path
|
|
name: teamID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Members
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/TeamMembership"
|
|
/teams/{teamID}/invites:
|
|
get:
|
|
summary: List pending team invites
|
|
parameters:
|
|
- in: path
|
|
name: teamID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Pending invites
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/TeamInvite"
|
|
post:
|
|
summary: Create team invite
|
|
parameters:
|
|
- in: path
|
|
name: teamID
|
|
required: true
|
|
schema: { type: string }
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [email, role]
|
|
properties:
|
|
email: { type: string, format: email }
|
|
role: { type: string, enum: [admin, editor, viewer] }
|
|
responses:
|
|
"201":
|
|
description: Invite and one-time token
|
|
/invites/accept:
|
|
post:
|
|
summary: Accept invite token as current user
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [token]
|
|
properties:
|
|
token: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Accepted membership
|
|
/drawings:
|
|
get:
|
|
summary: List drawings visible to current user
|
|
parameters:
|
|
- in: query
|
|
name: team_id
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Drawings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Drawing"
|
|
post:
|
|
summary: Create drawing
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [title]
|
|
properties:
|
|
team_id: { type: [string, "null"] }
|
|
folder_id: { type: [string, "null"] }
|
|
project_id: { type: [string, "null"] }
|
|
title: { type: string }
|
|
description: { type: [string, "null"] }
|
|
visibility: { type: string }
|
|
snapshot: {}
|
|
responses:
|
|
"201":
|
|
description: Created drawing
|
|
/drawings/{drawingID}:
|
|
get:
|
|
summary: Get drawing metadata
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Drawing
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Drawing"
|
|
patch:
|
|
summary: Update drawing metadata
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Updated drawing
|
|
delete:
|
|
summary: Archive drawing
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"204":
|
|
description: Archived
|
|
/drawings/{drawingID}/revisions:
|
|
get:
|
|
summary: List drawing revisions
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Revisions
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/DrawingRevision"
|
|
post:
|
|
summary: Create immutable drawing revision
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"201":
|
|
description: Revision created
|
|
/drawings/{drawingID}/permissions:
|
|
get:
|
|
summary: List explicit drawing permissions
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Permission grants
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/PermissionGrant"
|
|
post:
|
|
summary: Grant explicit drawing permission
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"201":
|
|
description: Created permission grant
|
|
/drawings/{drawingID}/share-links:
|
|
get:
|
|
summary: List active drawing share links
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Share links without token hashes
|
|
post:
|
|
summary: Create drawing share link
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"201":
|
|
description: Created share link and one-time token
|
|
/shared/{token}:
|
|
get:
|
|
security: []
|
|
summary: Resolve public share token
|
|
parameters:
|
|
- in: path
|
|
name: token
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Shared resource payload
|
|
/drawings/{drawingID}/assets:
|
|
get:
|
|
summary: List drawing asset metadata
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Assets
|
|
post:
|
|
summary: Create drawing asset metadata
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"201":
|
|
description: Created asset metadata
|
|
/drawings/{drawingID}/embeds:
|
|
get:
|
|
summary: List drawing embeds
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Embeds
|
|
post:
|
|
summary: Create safe drawing embed metadata
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"201":
|
|
description: Created embed metadata
|
|
/drawings/{drawingID}/links:
|
|
get:
|
|
summary: List drawing link references
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Link references
|
|
post:
|
|
summary: Create drawing link reference
|
|
parameters:
|
|
- in: path
|
|
name: drawingID
|
|
required: true
|
|
schema: { type: string }
|
|
responses:
|
|
"201":
|
|
description: Created link reference
|
|
/templates:
|
|
get:
|
|
summary: List system and accessible team templates
|
|
parameters:
|
|
- in: query
|
|
name: team_id
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Templates
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Template"
|
|
/activity:
|
|
get:
|
|
summary: List recent activity for accessible teams
|
|
parameters:
|
|
- in: query
|
|
name: team_id
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Activity
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/ActivityEvent"
|
|
/stats:
|
|
get:
|
|
summary: Workspace counts and storage usage
|
|
parameters:
|
|
- in: query
|
|
name: team_id
|
|
schema: { type: string }
|
|
responses:
|
|
"200":
|
|
description: Workspace stats
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/WorkspaceStats"
|
|
/folders:
|
|
get:
|
|
summary: List folders
|
|
responses:
|
|
"200":
|
|
description: Folders
|
|
post:
|
|
summary: Create folder
|
|
responses:
|
|
"201":
|
|
description: Created folder
|
|
/projects:
|
|
get:
|
|
summary: List projects
|
|
responses:
|
|
"200":
|
|
description: Projects
|
|
post:
|
|
summary: Create project
|
|
responses:
|
|
"201":
|
|
description: Created project
|