Add OpenAPI documentation
This commit is contained in:
parent
86c40aee91
commit
768939c22f
19
README.md
19
README.md
@ -93,6 +93,25 @@ http://127.0.0.1:8000/login.html
|
||||
|
||||
Keep both terminals open while using the app.
|
||||
|
||||
### API Documentation
|
||||
|
||||
The backend API is documented with an OpenAPI/Swagger specification:
|
||||
|
||||
```text
|
||||
backend/openapi.yaml
|
||||
```
|
||||
|
||||
To view the interactive documentation, open [Swagger Editor](https://editor.swagger.io/)
|
||||
and import `backend/openapi.yaml`. To make requests, start the backend and use
|
||||
`http://127.0.0.1:5000`. Browser cookie policies may make authenticated requests
|
||||
from the hosted Swagger Editor unreliable, so the app or an API client may be
|
||||
easier for testing authenticated endpoints.
|
||||
|
||||
The API uses a Flask session cookie for authentication. Register or log in first,
|
||||
then include the returned `session` cookie in authenticated requests. The
|
||||
specification documents all authentication, user, journey, comment, image upload,
|
||||
uploaded-file, and health endpoints.
|
||||
|
||||
### Daily Development Workflow
|
||||
|
||||
1. Start the backend in `backend/`.
|
||||
|
||||
942
backend/openapi.yaml
Normal file
942
backend/openapi.yaml
Normal file
@ -0,0 +1,942 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Journey Mapper API
|
||||
version: 1.0.0
|
||||
description: |
|
||||
Backend API for the Journey Mapper application.
|
||||
|
||||
Authentication uses a Flask session cookie. After registering or logging in,
|
||||
clients must send the returned `session` cookie with authenticated requests.
|
||||
Browser requests from the frontend must use credentials, for example
|
||||
`fetch(url, { credentials: "include" })`.
|
||||
|
||||
Journey and marker descriptions support Markdown. Raw HTML is stored as text
|
||||
and escaped by the frontend when rendered.
|
||||
servers:
|
||||
- url: http://127.0.0.1:5000
|
||||
description: Local development backend
|
||||
|
||||
tags:
|
||||
- name: Authentication
|
||||
- name: Users
|
||||
- name: Journeys
|
||||
- name: Comments
|
||||
- name: Uploads
|
||||
- name: System
|
||||
|
||||
paths:
|
||||
/api/register:
|
||||
post:
|
||||
tags: [Authentication]
|
||||
summary: Register a user
|
||||
description: Creates a user, starts a session, and returns the new public user data.
|
||||
operationId: registerUser
|
||||
security: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/AuthRequest"
|
||||
example:
|
||||
username: traveller
|
||||
password: secret123
|
||||
responses:
|
||||
"201":
|
||||
description: Registration successful
|
||||
headers:
|
||||
Set-Cookie:
|
||||
description: Flask session cookie used for authenticated requests.
|
||||
schema:
|
||||
type: string
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/AuthResponse"
|
||||
example:
|
||||
id: 1
|
||||
username: traveller
|
||||
message: Registration successful
|
||||
"400":
|
||||
$ref: "#/components/responses/ValidationError"
|
||||
"409":
|
||||
description: Username is already taken
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
example:
|
||||
error: Username already taken
|
||||
|
||||
/api/login:
|
||||
post:
|
||||
tags: [Authentication]
|
||||
summary: Log in
|
||||
description: Validates the credentials and starts a session.
|
||||
operationId: loginUser
|
||||
security: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/AuthRequest"
|
||||
example:
|
||||
username: traveller
|
||||
password: secret123
|
||||
responses:
|
||||
"200":
|
||||
description: Login successful
|
||||
headers:
|
||||
Set-Cookie:
|
||||
description: Flask session cookie used for authenticated requests.
|
||||
schema:
|
||||
type: string
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/AuthResponse"
|
||||
example:
|
||||
id: 1
|
||||
username: traveller
|
||||
message: Login successful
|
||||
"400":
|
||||
$ref: "#/components/responses/ValidationError"
|
||||
"401":
|
||||
description: Invalid username or password
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
example:
|
||||
error: Invalid username or password
|
||||
|
||||
/api/logout:
|
||||
post:
|
||||
tags: [Authentication]
|
||||
summary: Log out
|
||||
description: Removes the user ID from the current session. This operation also succeeds if no session exists.
|
||||
operationId: logoutUser
|
||||
security: []
|
||||
responses:
|
||||
"200":
|
||||
description: Logged out
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Message"
|
||||
example:
|
||||
message: Logged out
|
||||
|
||||
/api/me:
|
||||
get:
|
||||
tags: [Authentication]
|
||||
summary: Get the current user
|
||||
operationId: getCurrentUser
|
||||
responses:
|
||||
"200":
|
||||
description: Current public user data
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/User"
|
||||
"401":
|
||||
$ref: "#/components/responses/NotLoggedIn"
|
||||
|
||||
/api/users:
|
||||
get:
|
||||
tags: [Users]
|
||||
summary: List other users
|
||||
description: Returns every public user except the currently logged-in user.
|
||||
operationId: listUsers
|
||||
responses:
|
||||
"200":
|
||||
description: Public users
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/User"
|
||||
"401":
|
||||
$ref: "#/components/responses/AuthenticationRequired"
|
||||
|
||||
/api/journeys:
|
||||
get:
|
||||
tags: [Journeys]
|
||||
summary: List visible journeys
|
||||
description: |
|
||||
Returns journeys owned by the current user, public journeys, and journeys
|
||||
shared with the current user. Each returned journey contains a `can_edit`
|
||||
flag calculated for the current user.
|
||||
operationId: listJourneys
|
||||
responses:
|
||||
"200":
|
||||
description: Visible journeys
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/JourneyListItem"
|
||||
"401":
|
||||
$ref: "#/components/responses/AuthenticationRequired"
|
||||
post:
|
||||
tags: [Journeys]
|
||||
summary: Create a journey
|
||||
description: |
|
||||
Creates a journey owned by the current user. Supplied comments and
|
||||
server-managed fields such as IDs and timestamps are ignored.
|
||||
operationId: createJourney
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/JourneyCreate"
|
||||
responses:
|
||||
"201":
|
||||
description: Journey created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Journey"
|
||||
"400":
|
||||
$ref: "#/components/responses/ValidationError"
|
||||
"401":
|
||||
$ref: "#/components/responses/AuthenticationRequired"
|
||||
|
||||
/api/journeys/{journeyId}:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/JourneyId"
|
||||
get:
|
||||
tags: [Journeys]
|
||||
summary: Get a journey
|
||||
operationId: getJourney
|
||||
responses:
|
||||
"200":
|
||||
description: Journey data
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Journey"
|
||||
"401":
|
||||
$ref: "#/components/responses/AuthenticationRequired"
|
||||
"403":
|
||||
description: The current user cannot view this journey
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
example:
|
||||
error: Access denied
|
||||
"404":
|
||||
$ref: "#/components/responses/JourneyNotFound"
|
||||
put:
|
||||
tags: [Journeys]
|
||||
summary: Update a journey
|
||||
description: |
|
||||
The owner and users with shared edit access may update the title,
|
||||
description, and markers. Only the owner may update visibility or sharing.
|
||||
Omitted fields remain unchanged.
|
||||
operationId: updateJourney
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/JourneyUpdate"
|
||||
responses:
|
||||
"200":
|
||||
description: Journey updated
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Journey"
|
||||
"400":
|
||||
$ref: "#/components/responses/ValidationError"
|
||||
"401":
|
||||
$ref: "#/components/responses/AuthenticationRequired"
|
||||
"403":
|
||||
description: The current user cannot edit the journey or its sharing settings
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
examples:
|
||||
cannotEdit:
|
||||
value:
|
||||
error: Not authorized to edit this journey
|
||||
sharingOwnerOnly:
|
||||
value:
|
||||
error: Only the owner can update sharing settings
|
||||
"404":
|
||||
$ref: "#/components/responses/JourneyNotFound"
|
||||
delete:
|
||||
tags: [Journeys]
|
||||
summary: Delete a journey
|
||||
description: Only the journey owner may delete it.
|
||||
operationId: deleteJourney
|
||||
responses:
|
||||
"200":
|
||||
description: Journey deleted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [message, journey]
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
journey:
|
||||
$ref: "#/components/schemas/Journey"
|
||||
example:
|
||||
message: Journey deleted successfully
|
||||
journey:
|
||||
id: 1
|
||||
owner_id: 1
|
||||
title: Switzerland
|
||||
description: My summer journey
|
||||
markers: []
|
||||
created_at: "2026-06-07T18:30:00"
|
||||
visibility: private
|
||||
shared_read: []
|
||||
shared_edit: []
|
||||
comments: []
|
||||
"401":
|
||||
$ref: "#/components/responses/AuthenticationRequired"
|
||||
"403":
|
||||
description: Only the journey owner may delete it
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
example:
|
||||
error: Only the owner can delete this journey
|
||||
"404":
|
||||
$ref: "#/components/responses/JourneyNotFound"
|
||||
|
||||
/api/journeys/{journeyId}/comments:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/JourneyId"
|
||||
get:
|
||||
tags: [Comments]
|
||||
summary: List journey comments
|
||||
description: The current user must be able to view the journey.
|
||||
operationId: listJourneyComments
|
||||
responses:
|
||||
"200":
|
||||
description: Journey comments
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Comment"
|
||||
"401":
|
||||
$ref: "#/components/responses/AuthenticationRequired"
|
||||
"403":
|
||||
description: The current user cannot view the journey
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
example:
|
||||
error: Access denied
|
||||
"404":
|
||||
$ref: "#/components/responses/JourneyNotFound"
|
||||
post:
|
||||
tags: [Comments]
|
||||
summary: Add a journey comment
|
||||
description: The current user must be able to view the journey.
|
||||
operationId: addJourneyComment
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/CommentCreate"
|
||||
example:
|
||||
text: This looks like a wonderful trip.
|
||||
responses:
|
||||
"201":
|
||||
description: Comment created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Comment"
|
||||
"400":
|
||||
$ref: "#/components/responses/ValidationError"
|
||||
"401":
|
||||
$ref: "#/components/responses/AuthenticationRequired"
|
||||
"403":
|
||||
description: The current user cannot view the journey
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
example:
|
||||
error: Access denied
|
||||
"404":
|
||||
$ref: "#/components/responses/JourneyNotFound"
|
||||
|
||||
/api/comments/{commentId}:
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/CommentId"
|
||||
delete:
|
||||
tags: [Comments]
|
||||
summary: Delete a comment
|
||||
description: A comment may be deleted by its author or the journey owner.
|
||||
operationId: deleteComment
|
||||
responses:
|
||||
"200":
|
||||
description: Comment deleted
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Message"
|
||||
example:
|
||||
message: Comment deleted
|
||||
"401":
|
||||
$ref: "#/components/responses/AuthenticationRequired"
|
||||
"403":
|
||||
description: The current user cannot delete the comment
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
example:
|
||||
error: Not authorized
|
||||
"404":
|
||||
description: Comment not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
example:
|
||||
error: Comment not found
|
||||
|
||||
/api/uploads/images:
|
||||
post:
|
||||
tags: [Uploads]
|
||||
summary: Upload marker images
|
||||
description: |
|
||||
Uploads one or more images using repeated `images` form fields. Accepted
|
||||
filename extensions are `.png`, `.jpg`, `.jpeg`, `.gif`, and `.webp`.
|
||||
The returned image objects can be included in a marker's `images` array.
|
||||
operationId: uploadImages
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
multipart/form-data:
|
||||
schema:
|
||||
type: object
|
||||
required: [images]
|
||||
properties:
|
||||
images:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
format: binary
|
||||
responses:
|
||||
"201":
|
||||
description: Images uploaded
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [images]
|
||||
properties:
|
||||
images:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Image"
|
||||
"400":
|
||||
description: No valid images were provided or an extension is unsupported
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
examples:
|
||||
noImages:
|
||||
value:
|
||||
error: No images provided
|
||||
unsupported:
|
||||
value:
|
||||
error: "Unsupported image type: notes.txt"
|
||||
"401":
|
||||
$ref: "#/components/responses/AuthenticationRequired"
|
||||
|
||||
/uploads/{filename}:
|
||||
parameters:
|
||||
- name: filename
|
||||
in: path
|
||||
required: true
|
||||
description: Server-generated image filename returned by the upload endpoint.
|
||||
schema:
|
||||
type: string
|
||||
example: 79ce8a0727d846f4bffb1fbf94365191.jpg
|
||||
get:
|
||||
tags: [Uploads]
|
||||
summary: Get an uploaded image
|
||||
description: Uploaded images are publicly accessible.
|
||||
operationId: getUploadedImage
|
||||
security: []
|
||||
responses:
|
||||
"200":
|
||||
description: Image file
|
||||
content:
|
||||
image/png:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
image/jpeg:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
image/gif:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
image/webp:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
"404":
|
||||
description: Image not found
|
||||
|
||||
/api/journeys/health:
|
||||
get:
|
||||
tags: [System]
|
||||
summary: Check API health
|
||||
operationId: getHealth
|
||||
security: []
|
||||
responses:
|
||||
"200":
|
||||
description: Backend is healthy
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Health"
|
||||
|
||||
/:
|
||||
get:
|
||||
tags: [System]
|
||||
summary: Get the API landing page
|
||||
description: Returns a small HTML page confirming that the backend is running.
|
||||
operationId: getApiLandingPage
|
||||
security: []
|
||||
responses:
|
||||
"200":
|
||||
description: API landing page
|
||||
content:
|
||||
text/html:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
cookieAuth:
|
||||
type: apiKey
|
||||
in: cookie
|
||||
name: session
|
||||
description: Flask session cookie returned after registration or login.
|
||||
|
||||
parameters:
|
||||
JourneyId:
|
||||
name: journeyId
|
||||
in: path
|
||||
required: true
|
||||
description: Journey ID
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 1
|
||||
CommentId:
|
||||
name: commentId
|
||||
in: path
|
||||
required: true
|
||||
description: Millisecond timestamp used as the comment ID
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
minimum: 1
|
||||
|
||||
responses:
|
||||
ValidationError:
|
||||
description: Request validation failed
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
examples:
|
||||
missingTitle:
|
||||
value:
|
||||
error: Journey title is required
|
||||
invalidCoordinates:
|
||||
value:
|
||||
error: Marker latitude must be between -90 and 90
|
||||
AuthenticationRequired:
|
||||
description: Authentication is required
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
example:
|
||||
error: Authentication required
|
||||
NotLoggedIn:
|
||||
description: There is no valid current user session
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
examples:
|
||||
noSession:
|
||||
value:
|
||||
error: Not logged in
|
||||
missingUser:
|
||||
value:
|
||||
error: User not found
|
||||
JourneyNotFound:
|
||||
description: Journey not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
example:
|
||||
error: Journey not found
|
||||
|
||||
schemas:
|
||||
Error:
|
||||
type: object
|
||||
required: [error]
|
||||
additionalProperties: false
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
|
||||
Message:
|
||||
type: object
|
||||
required: [message]
|
||||
additionalProperties: false
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
|
||||
User:
|
||||
type: object
|
||||
required: [id, username]
|
||||
additionalProperties: false
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
minimum: 1
|
||||
username:
|
||||
type: string
|
||||
maxLength: 50
|
||||
|
||||
AuthRequest:
|
||||
type: object
|
||||
required: [username, password]
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
minLength: 1
|
||||
maxLength: 50
|
||||
password:
|
||||
type: string
|
||||
format: password
|
||||
minLength: 4
|
||||
maxLength: 200
|
||||
|
||||
AuthResponse:
|
||||
type: object
|
||||
required: [id, username, message]
|
||||
additionalProperties: false
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
minimum: 1
|
||||
username:
|
||||
type: string
|
||||
maxLength: 50
|
||||
message:
|
||||
type: string
|
||||
|
||||
Image:
|
||||
type: object
|
||||
required: [filename, originalName, url]
|
||||
additionalProperties: false
|
||||
properties:
|
||||
filename:
|
||||
type: string
|
||||
maxLength: 255
|
||||
description: Server-generated filename.
|
||||
originalName:
|
||||
type: string
|
||||
maxLength: 255
|
||||
description: Sanitized original filename.
|
||||
url:
|
||||
type: string
|
||||
maxLength: 2048
|
||||
description: Relative or absolute image URL.
|
||||
example: /uploads/79ce8a0727d846f4bffb1fbf94365191.jpg
|
||||
|
||||
MarkerImageInput:
|
||||
description: A marker image may be supplied as a URL string or a full image object.
|
||||
oneOf:
|
||||
- type: string
|
||||
minLength: 1
|
||||
maxLength: 2048
|
||||
- $ref: "#/components/schemas/Image"
|
||||
|
||||
Marker:
|
||||
type: object
|
||||
required: [lat, lng, title, date, description, images]
|
||||
additionalProperties: false
|
||||
properties:
|
||||
lat:
|
||||
type: number
|
||||
format: double
|
||||
minimum: -90
|
||||
maximum: 90
|
||||
lng:
|
||||
type: number
|
||||
format: double
|
||||
minimum: -180
|
||||
maximum: 180
|
||||
title:
|
||||
type: string
|
||||
maxLength: 200
|
||||
date:
|
||||
type: string
|
||||
maxLength: 20
|
||||
description: Date text, normally formatted as `YYYY-MM-DD`.
|
||||
example: "2026-06-07"
|
||||
description:
|
||||
type: string
|
||||
maxLength: 10000
|
||||
description: Markdown-supported marker description.
|
||||
images:
|
||||
type: array
|
||||
maxItems: 20
|
||||
items:
|
||||
$ref: "#/components/schemas/MarkerImageInput"
|
||||
|
||||
MarkerInput:
|
||||
type: object
|
||||
required: [lat, lng]
|
||||
properties:
|
||||
lat:
|
||||
type: number
|
||||
format: double
|
||||
minimum: -90
|
||||
maximum: 90
|
||||
lng:
|
||||
type: number
|
||||
format: double
|
||||
minimum: -180
|
||||
maximum: 180
|
||||
title:
|
||||
type: string
|
||||
maxLength: 200
|
||||
default: ""
|
||||
date:
|
||||
type: string
|
||||
maxLength: 20
|
||||
default: ""
|
||||
example: "2026-06-07"
|
||||
description:
|
||||
type: string
|
||||
maxLength: 10000
|
||||
default: ""
|
||||
description: Markdown-supported marker description.
|
||||
images:
|
||||
type: array
|
||||
maxItems: 20
|
||||
default: []
|
||||
items:
|
||||
$ref: "#/components/schemas/MarkerImageInput"
|
||||
|
||||
Comment:
|
||||
type: object
|
||||
required: [id, author_id, author_name, text, created_at]
|
||||
additionalProperties: false
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
minimum: 1
|
||||
author_id:
|
||||
type: integer
|
||||
minimum: 1
|
||||
author_name:
|
||||
type: string
|
||||
maxLength: 50
|
||||
text:
|
||||
type: string
|
||||
minLength: 1
|
||||
maxLength: 2000
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
CommentCreate:
|
||||
type: object
|
||||
required: [text]
|
||||
properties:
|
||||
text:
|
||||
type: string
|
||||
minLength: 1
|
||||
maxLength: 2000
|
||||
|
||||
Visibility:
|
||||
type: string
|
||||
enum: [private, public, shared]
|
||||
default: private
|
||||
|
||||
Journey:
|
||||
type: object
|
||||
required:
|
||||
- id
|
||||
- owner_id
|
||||
- title
|
||||
- description
|
||||
- markers
|
||||
- created_at
|
||||
- visibility
|
||||
- shared_read
|
||||
- shared_edit
|
||||
- comments
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
minimum: 1
|
||||
owner_id:
|
||||
type: integer
|
||||
minimum: 1
|
||||
title:
|
||||
type: string
|
||||
minLength: 1
|
||||
maxLength: 200
|
||||
description:
|
||||
type: string
|
||||
maxLength: 20000
|
||||
description: Markdown-supported journey description.
|
||||
markers:
|
||||
type: array
|
||||
maxItems: 500
|
||||
items:
|
||||
$ref: "#/components/schemas/Marker"
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
visibility:
|
||||
$ref: "#/components/schemas/Visibility"
|
||||
shared_read:
|
||||
type: array
|
||||
uniqueItems: true
|
||||
items:
|
||||
type: integer
|
||||
minimum: 1
|
||||
shared_edit:
|
||||
type: array
|
||||
uniqueItems: true
|
||||
items:
|
||||
type: integer
|
||||
minimum: 1
|
||||
comments:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Comment"
|
||||
|
||||
JourneyListItem:
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/Journey"
|
||||
- type: object
|
||||
required: [can_edit]
|
||||
properties:
|
||||
can_edit:
|
||||
type: boolean
|
||||
description: Whether the current user may edit this journey.
|
||||
|
||||
JourneyCreate:
|
||||
type: object
|
||||
required: [title]
|
||||
properties:
|
||||
title:
|
||||
type: string
|
||||
minLength: 1
|
||||
maxLength: 200
|
||||
description:
|
||||
type: string
|
||||
maxLength: 20000
|
||||
default: ""
|
||||
description: Markdown-supported journey description.
|
||||
markers:
|
||||
type: array
|
||||
maxItems: 500
|
||||
default: []
|
||||
items:
|
||||
$ref: "#/components/schemas/MarkerInput"
|
||||
visibility:
|
||||
$ref: "#/components/schemas/Visibility"
|
||||
shared_read:
|
||||
type: array
|
||||
default: []
|
||||
description: Invalid, duplicate, and unknown user IDs are silently removed.
|
||||
items:
|
||||
type: integer
|
||||
minimum: 1
|
||||
shared_edit:
|
||||
type: array
|
||||
default: []
|
||||
description: Invalid, duplicate, and unknown user IDs are silently removed.
|
||||
items:
|
||||
type: integer
|
||||
minimum: 1
|
||||
|
||||
JourneyUpdate:
|
||||
type: object
|
||||
properties:
|
||||
title:
|
||||
type: string
|
||||
minLength: 1
|
||||
maxLength: 200
|
||||
description:
|
||||
type: string
|
||||
maxLength: 20000
|
||||
description: Markdown-supported journey description.
|
||||
markers:
|
||||
type: array
|
||||
maxItems: 500
|
||||
items:
|
||||
$ref: "#/components/schemas/MarkerInput"
|
||||
visibility:
|
||||
$ref: "#/components/schemas/Visibility"
|
||||
shared_read:
|
||||
type: array
|
||||
description: Owner-only field. Invalid, duplicate, and unknown user IDs are silently removed.
|
||||
items:
|
||||
type: integer
|
||||
minimum: 1
|
||||
shared_edit:
|
||||
type: array
|
||||
description: Owner-only field. Invalid, duplicate, and unknown user IDs are silently removed.
|
||||
items:
|
||||
type: integer
|
||||
minimum: 1
|
||||
|
||||
Health:
|
||||
type: object
|
||||
required: [status, timestamp]
|
||||
additionalProperties: false
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: [healthy]
|
||||
timestamp:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
security:
|
||||
- cookieAuth: []
|
||||
Loading…
x
Reference in New Issue
Block a user