openapi: 3.0.3 info: title: Packs Site API description: | API for the Packs Site. All endpoints are behind the site's gate (master password) and most require authentication. ## Authentication Requests authenticate with an API token in the `Authorization` header: Authorization: Bearer Tokens are created on the **API Tokens** settings page. Without a valid token (or a logged-in browser session) API requests get a `401` response. Staff-only endpoints return `403` for non-staff. version: 1.0.0 servers: - url: / tags: - name: Files description: Serving stored files - name: Uploads description: Draft/temp upload management - name: Drafts description: Create-page autosave - name: Search description: Autocomplete endpoints - name: Packs description: Pack update-check - name: Stats description: Server statistics paths: /api/files/{file_id}/: get: tags: [Files] summary: Serve a stored file description: Serves any stored file (media, release zips, textures). Use `download=1` to force an attachment. parameters: - name: file_id in: path required: true description: UUID of the stored file. schema: { type: string, format: uuid } - name: download in: query required: false description: Set to `1` to force a download attachment. schema: { type: string } responses: "200": description: The file contents. content: application/octet-stream: schema: { type: string, format: binary } "401": $ref: "#/components/responses/Unauthorized" "404": description: File not found. /api/uploads/: post: tags: [Uploads] summary: Upload a temporary file description: Uploads a file into the current draft / upload pool. Returns the upload record used by the create-page UI. security: - bearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object properties: file: type: string format: binary description: The file to upload. kind: type: string enum: [thumbnail, version, media] default: media draft_uuid: type: string format: uuid description: Scope the upload to a specific create-page draft (optional). responses: "200": description: Upload accepted. content: application/json: schema: $ref: "#/components/schemas/TempUpload" "400": description: Invalid file type for the requested kind. "401": $ref: "#/components/responses/Unauthorized" /api/uploads/{upload_uuid}/delete/: post: tags: [Uploads] summary: Delete a temporary upload description: Removes a pending upload and its stored file. Only the owner may delete it. security: - bearerAuth: [] parameters: - name: upload_uuid in: path required: true schema: { type: string, format: uuid } responses: "200": description: Deleted. content: application/json: schema: type: object properties: success: { type: boolean } "401": $ref: "#/components/responses/Unauthorized" "404": description: Upload not found. /api/draft/: get: tags: [Drafts] summary: Load a draft description: Returns the saved form data and pending uploads for one draft. security: - bearerAuth: [] parameters: - name: draft in: query required: true description: The draft UUID. schema: { type: string, format: uuid } responses: "200": description: Draft data + uploads. content: application/json: schema: $ref: "#/components/schemas/DraftData" "401": $ref: "#/components/responses/Unauthorized" "404": description: Draft not found or not owned by you. post: tags: [Drafts] summary: Autosave a draft description: Persists the create-page form fields for a draft (debounced autosave). security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [draft] properties: draft: type: string format: uuid data: type: object description: Form fields (title, summary, category, description, tags, version_name, changelog). responses: "200": description: Saved. content: application/json: schema: type: object properties: saved: { type: boolean } updated_at: { type: string, format: date-time } "401": $ref: "#/components/responses/Unauthorized" "404": description: Draft not found or not owned by you. delete: tags: [Drafts] summary: Delete a draft description: Deletes the draft and purges its pending uploads. security: - bearerAuth: [] parameters: - name: draft in: query required: true schema: { type: string, format: uuid } responses: "200": description: Deleted. content: application/json: schema: type: object properties: success: { type: boolean } "401": $ref: "#/components/responses/Unauthorized" "404": description: Draft not found or not owned by you. /api/tags/autocomplete/: get: tags: [Search] summary: Tag autocomplete parameters: - name: q in: query required: false description: Partial tag or category name. schema: { type: string } responses: "200": description: Matching tags. content: application/json: schema: type: array items: type: object properties: name: { type: string } category: { type: string } category_name: { type: string } color: { type: string } "401": $ref: "#/components/responses/Unauthorized" /api/users/autocomplete/: get: tags: [Search] summary: User autocomplete parameters: - name: q in: query required: false description: Partial username. schema: { type: string } responses: "200": description: Matching usernames. content: application/json: schema: type: array items: type: object properties: username: { type: string } "401": $ref: "#/components/responses/Unauthorized" /api/packs/{namespace}/{pack_id}/latest: get: tags: [Packs] summary: Pack update-check description: Newest version for a NeedsOfNature pack id (`namespace:pack_id`), used by the mod's auto-updater. parameters: - name: namespace in: path required: true schema: { type: string } - name: pack_id in: path required: true schema: { type: string } responses: "200": description: Latest version info. content: application/json: schema: $ref: "#/components/schemas/PackLatest" "401": $ref: "#/components/responses/Unauthorized" "404": description: Pack not found. /api/stats/: get: tags: [Stats] summary: Server statistics description: One-shot server/performance snapshot. Staff only. Responses are cached ~20s server-side. security: - bearerAuth: [] responses: "200": description: Snapshot payload. content: application/json: schema: type: object additionalProperties: true "401": $ref: "#/components/responses/Unauthorized" "403": description: Staff only. components: securitySchemes: bearerAuth: type: apiKey in: header name: Authorization description: "API token authentication: `Bearer `." responses: Unauthorized: description: Missing or invalid credentials. content: application/json: schema: type: object properties: detail: { type: string } example: { detail: Unauthorized } schemas: TempUpload: type: object properties: uuid: { type: string, format: uuid } kind: { type: string, enum: [thumbnail, version, media] } filename: { type: string } content_type: { type: string } url: { type: string } DraftData: type: object properties: data: type: object additionalProperties: true uploads: type: array items: $ref: "#/components/schemas/TempUpload" PackLatest: type: object properties: namespace: { type: string } pack_id: { type: string } name: { type: string } version: { type: string } pack_format: { type: integer, nullable: true } created_at: { type: string, format: date-time } download_url: { type: string }