{ "openapi": "3.1.0", "info": { "title": "Fluxer Media Proxy API", "version": "1.0.0", "description": "Media proxy API for Fluxer. Serves avatars, icons, banners, attachments, emojis, stickers, and proxied external media.", "contact": { "name": "Fluxer Developers", "email": "developers@fluxer.app" }, "license": { "name": "AGPL-3.0", "url": "https://www.gnu.org/licenses/agpl-3.0.html" } }, "servers": [ { "url": "https://fluxerusercontent.com", "description": "Production media proxy" } ], "tags": [ { "name": "Images", "description": "User and guild images (avatars, icons, banners, splashes)" }, { "name": "Content", "description": "Emojis, stickers, and attachments" }, { "name": "External", "description": "Proxied external media" }, { "name": "Themes", "description": "Theme CSS files" }, { "name": "Internal", "description": "Internal endpoints for service-to-service communication" } ], "paths": { "/avatars/{id}/{filename}": { "get": { "operationId": "getAvatar", "summary": "Get user or guild avatar", "description": "Retrieve a user or guild avatar image. Supports animated avatars (GIF) when the filename starts with `a_`.", "tags": ["Images"], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "User or guild ID" }, { "name": "filename", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Avatar filename (hash.ext or a_hash.ext for animated)" }, { "$ref": "#/components/parameters/sizeParam" }, { "$ref": "#/components/parameters/formatParam" }, { "$ref": "#/components/parameters/qualityParam" }, { "$ref": "#/components/parameters/animatedParam" } ], "responses": { "200": { "description": "Image data", "content": { "image/png": { "schema": { "type": "string", "format": "binary" } }, "image/jpeg": { "schema": { "type": "string", "format": "binary" } }, "image/webp": { "schema": { "type": "string", "format": "binary" } }, "image/gif": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "description": "Bad request - invalid parameters" }, "404": { "description": "Resource not found" } } } }, "/icons/{id}/{filename}": { "get": { "operationId": "getIcon", "summary": "Get guild icon", "description": "Retrieve a guild icon image.", "tags": ["Images"], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Guild ID" }, { "name": "filename", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Icon filename" }, { "$ref": "#/components/parameters/sizeParam" }, { "$ref": "#/components/parameters/formatParam" }, { "$ref": "#/components/parameters/qualityParam" }, { "$ref": "#/components/parameters/animatedParam" } ], "responses": { "200": { "description": "Image data", "content": { "image/png": { "schema": { "type": "string", "format": "binary" } }, "image/jpeg": { "schema": { "type": "string", "format": "binary" } }, "image/webp": { "schema": { "type": "string", "format": "binary" } }, "image/gif": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "description": "Bad request - invalid parameters" }, "404": { "description": "Resource not found" } } } }, "/banners/{id}/{filename}": { "get": { "operationId": "getBanner", "summary": "Get user or guild banner", "description": "Retrieve a user or guild banner image.", "tags": ["Images"], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "User or guild ID" }, { "name": "filename", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Banner filename" }, { "$ref": "#/components/parameters/sizeParam" }, { "$ref": "#/components/parameters/formatParam" }, { "$ref": "#/components/parameters/qualityParam" }, { "$ref": "#/components/parameters/animatedParam" } ], "responses": { "200": { "description": "Image data", "content": { "image/png": { "schema": { "type": "string", "format": "binary" } }, "image/jpeg": { "schema": { "type": "string", "format": "binary" } }, "image/webp": { "schema": { "type": "string", "format": "binary" } }, "image/gif": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "description": "Bad request - invalid parameters" }, "404": { "description": "Resource not found" } } } }, "/splashes/{id}/{filename}": { "get": { "operationId": "getSplash", "summary": "Get guild invite splash", "description": "Retrieve a guild invite splash image.", "tags": ["Images"], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Guild ID" }, { "name": "filename", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Splash filename" }, { "$ref": "#/components/parameters/sizeParam" }, { "$ref": "#/components/parameters/formatParam" }, { "$ref": "#/components/parameters/qualityParam" }, { "$ref": "#/components/parameters/animatedParam" } ], "responses": { "200": { "description": "Image data", "content": { "image/png": { "schema": { "type": "string", "format": "binary" } }, "image/jpeg": { "schema": { "type": "string", "format": "binary" } }, "image/webp": { "schema": { "type": "string", "format": "binary" } }, "image/gif": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "description": "Bad request - invalid parameters" }, "404": { "description": "Resource not found" } } } }, "/embed-splashes/{id}/{filename}": { "get": { "operationId": "getEmbedSplash", "summary": "Get guild embed splash", "description": "Retrieve a guild embed splash image (used for server previews).", "tags": ["Images"], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Guild ID" }, { "name": "filename", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Embed splash filename" }, { "$ref": "#/components/parameters/sizeParam" }, { "$ref": "#/components/parameters/formatParam" }, { "$ref": "#/components/parameters/qualityParam" }, { "$ref": "#/components/parameters/animatedParam" } ], "responses": { "200": { "description": "Image data", "content": { "image/png": { "schema": { "type": "string", "format": "binary" } }, "image/jpeg": { "schema": { "type": "string", "format": "binary" } }, "image/webp": { "schema": { "type": "string", "format": "binary" } }, "image/gif": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "description": "Bad request - invalid parameters" }, "404": { "description": "Resource not found" } } } }, "/emojis/{id}": { "get": { "operationId": "getEmoji", "summary": "Get custom emoji", "description": "Retrieve a custom emoji image. May be PNG, GIF, or WebP.", "tags": ["Content"], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Emoji ID" }, { "$ref": "#/components/parameters/sizeParam" }, { "$ref": "#/components/parameters/formatParam" }, { "$ref": "#/components/parameters/qualityParam" }, { "$ref": "#/components/parameters/animatedParam" } ], "responses": { "200": { "description": "Image data", "content": { "image/png": { "schema": { "type": "string", "format": "binary" } }, "image/jpeg": { "schema": { "type": "string", "format": "binary" } }, "image/webp": { "schema": { "type": "string", "format": "binary" } }, "image/gif": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "description": "Bad request - invalid parameters" }, "404": { "description": "Resource not found" } } } }, "/stickers/{id}": { "get": { "operationId": "getSticker", "summary": "Get sticker", "description": "Retrieve a sticker image or Lottie animation. May return PNG, APNG, GIF, or Lottie JSON.", "tags": ["Content"], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Sticker ID" }, { "$ref": "#/components/parameters/sizeParam" }, { "$ref": "#/components/parameters/formatParam" }, { "$ref": "#/components/parameters/qualityParam" }, { "$ref": "#/components/parameters/animatedParam" } ], "responses": { "200": { "description": "Sticker data", "content": { "image/png": { "schema": { "type": "string", "format": "binary" } }, "image/apng": { "schema": { "type": "string", "format": "binary" } }, "image/gif": { "schema": { "type": "string", "format": "binary" } }, "application/json": { "schema": { "type": "object", "description": "Lottie animation JSON" } } } }, "404": { "description": "Sticker not found" } } } }, "/guilds/{guild_id}/users/{user_id}/avatars/{filename}": { "get": { "operationId": "getGuildMemberAvatar", "summary": "Get guild member avatar", "description": "Retrieve a guild-specific member avatar.", "tags": ["Images"], "parameters": [ { "name": "guild_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Guild ID" }, { "name": "user_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "User ID" }, { "name": "filename", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Avatar filename" }, { "$ref": "#/components/parameters/sizeParam" }, { "$ref": "#/components/parameters/formatParam" }, { "$ref": "#/components/parameters/qualityParam" }, { "$ref": "#/components/parameters/animatedParam" } ], "responses": { "200": { "description": "Image data", "content": { "image/png": { "schema": { "type": "string", "format": "binary" } }, "image/jpeg": { "schema": { "type": "string", "format": "binary" } }, "image/webp": { "schema": { "type": "string", "format": "binary" } }, "image/gif": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "description": "Bad request - invalid parameters" }, "404": { "description": "Resource not found" } } } }, "/guilds/{guild_id}/users/{user_id}/banners/{filename}": { "get": { "operationId": "getGuildMemberBanner", "summary": "Get guild member banner", "description": "Retrieve a guild-specific member banner.", "tags": ["Images"], "parameters": [ { "name": "guild_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Guild ID" }, { "name": "user_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "User ID" }, { "name": "filename", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Banner filename" }, { "$ref": "#/components/parameters/sizeParam" }, { "$ref": "#/components/parameters/formatParam" }, { "$ref": "#/components/parameters/qualityParam" }, { "$ref": "#/components/parameters/animatedParam" } ], "responses": { "200": { "description": "Image data", "content": { "image/png": { "schema": { "type": "string", "format": "binary" } }, "image/jpeg": { "schema": { "type": "string", "format": "binary" } }, "image/webp": { "schema": { "type": "string", "format": "binary" } }, "image/gif": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "description": "Bad request - invalid parameters" }, "404": { "description": "Resource not found" } } } }, "/attachments/{channel_id}/{attachment_id}/{filename}": { "get": { "operationId": "getAttachment", "summary": "Get message attachment", "description": "Retrieve a message attachment. Supports images, videos, and other files. Image query parameters only apply to image attachments.", "tags": ["Content"], "parameters": [ { "name": "channel_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Channel ID" }, { "name": "attachment_id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Attachment ID" }, { "name": "filename", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Original filename" }, { "$ref": "#/components/parameters/sizeParam" }, { "$ref": "#/components/parameters/formatParam" }, { "$ref": "#/components/parameters/qualityParam" }, { "$ref": "#/components/parameters/animatedParam" } ], "responses": { "200": { "description": "File data with appropriate Content-Type", "content": { "*/*": { "schema": { "type": "string", "format": "binary" } } } }, "404": { "description": "Attachment not found" } } } }, "/themes/{id}.css": { "get": { "operationId": "getTheme", "summary": "Get theme CSS", "description": "Retrieve a theme CSS file.", "tags": ["Themes"], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Theme ID" } ], "responses": { "200": { "description": "Theme CSS", "content": { "text/css": { "schema": { "type": "string" } } } }, "404": { "description": "Theme not found" } } } }, "/external/{signature}/{timestamp}/{url}": { "get": { "operationId": "getExternalMedia", "summary": "Proxy external media", "description": "Proxy external media through the Fluxer media proxy. External URLs are signed with HMAC-SHA256 to prevent abuse. The signature and timestamp parameters ensure URLs cannot be forged and expire after a configured period.", "tags": ["External"], "parameters": [ { "name": "signature", "in": "path", "required": true, "schema": { "type": "string" }, "description": "HMAC-SHA256 signature of the URL and timestamp, hex-encoded" }, { "name": "timestamp", "in": "path", "required": true, "schema": { "type": "string" }, "description": "Unix timestamp (seconds) when the signature was generated, hex-encoded" }, { "name": "url", "in": "path", "required": true, "schema": { "type": "string" }, "description": "External URL with protocol prefix (e.g., https/example.com/image.jpg)" }, { "$ref": "#/components/parameters/widthParam" }, { "$ref": "#/components/parameters/heightParam" }, { "$ref": "#/components/parameters/formatParam" }, { "$ref": "#/components/parameters/qualityParam" }, { "$ref": "#/components/parameters/animatedParam" } ], "responses": { "200": { "description": "Image data", "content": { "image/png": { "schema": { "type": "string", "format": "binary" } }, "image/jpeg": { "schema": { "type": "string", "format": "binary" } }, "image/webp": { "schema": { "type": "string", "format": "binary" } }, "image/gif": { "schema": { "type": "string", "format": "binary" } } } }, "400": { "description": "Bad request - invalid parameters" }, "403": { "description": "Invalid signature or expired URL" }, "404": { "description": "Resource not found" }, "502": { "description": "Failed to fetch external resource" } } } }, "/_metadata": { "post": { "operationId": "extractMetadata", "summary": "Extract media metadata", "description": "Extract metadata from media files including dimensions, format, duration, NSFW detection, and optional base64 encoding.", "tags": ["Internal"], "security": [ { "internalKey": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MetadataRequest" } } } }, "responses": { "200": { "description": "Metadata extracted successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MetadataResponse" } } } }, "400": { "description": "Invalid request" }, "401": { "description": "Unauthorized" } } } }, "/_thumbnail": { "post": { "operationId": "generateThumbnail", "summary": "Generate video thumbnail", "description": "Generate a thumbnail from a video file.", "tags": ["Internal"], "security": [ { "internalKey": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThumbnailRequestBody" } } } }, "responses": { "200": { "description": "Thumbnail generated successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ThumbnailResponse" } } } }, "400": { "description": "Invalid request or unsupported video format" }, "401": { "description": "Unauthorized" } } } }, "/_frames": { "post": { "operationId": "extractFrames", "summary": "Extract video frames", "description": "Extract multiple frames from a video file at evenly distributed timestamps.", "tags": ["Internal"], "security": [ { "internalKey": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FrameRequest" } } } }, "responses": { "200": { "description": "Frames extracted successfully", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FrameResponse" } } } }, "400": { "description": "Invalid request or unsupported video format" }, "401": { "description": "Unauthorized" } } } } }, "components": { "schemas": { "ImageSizeEnum": { "type": "string", "enum": [ "16", "20", "22", "24", "28", "32", "40", "44", "48", "56", "60", "64", "80", "96", "100", "128", "160", "240", "256", "300", "320", "480", "512", "600", "640", "1024", "1280", "1536", "2048", "3072", "4096" ], "description": "Allowed image sizes in pixels", "example": "128" }, "ImageFormatEnum": { "type": "string", "enum": ["png", "jpg", "jpeg", "webp", "gif"], "description": "Allowed image output formats", "example": "webp" }, "ImageQualityEnum": { "type": "string", "enum": ["high", "low", "lossless"], "description": "Image quality levels: high (default), low (smaller files), lossless (no compression)", "example": "high" }, "MetadataRequestExternal": { "type": "object", "description": "Metadata request for external URLs", "properties": { "type": { "type": "string", "const": "external" }, "url": { "type": "string", "format": "uri", "description": "External URL to fetch" }, "with_base64": { "type": "boolean", "description": "Include base64-encoded content in response" }, "isNSFWAllowed": { "type": "boolean", "description": "Whether NSFW content is permitted" } }, "required": ["type", "url", "isNSFWAllowed"] }, "MetadataRequestUpload": { "type": "object", "description": "Metadata request for uploaded files", "properties": { "type": { "type": "string", "const": "upload" }, "upload_filename": { "type": "string", "description": "Filename in the uploads bucket" }, "isNSFWAllowed": { "type": "boolean", "description": "Whether NSFW content is permitted" } }, "required": ["type", "upload_filename", "isNSFWAllowed"] }, "MetadataRequestBase64": { "type": "object", "description": "Metadata request for base64-encoded data", "properties": { "type": { "type": "string", "const": "base64" }, "base64": { "type": "string", "description": "Base64-encoded media data" }, "isNSFWAllowed": { "type": "boolean", "description": "Whether NSFW content is permitted" } }, "required": ["type", "base64", "isNSFWAllowed"] }, "MetadataRequestS3": { "type": "object", "description": "Metadata request for S3 objects", "properties": { "type": { "type": "string", "const": "s3" }, "bucket": { "type": "string", "description": "S3 bucket name" }, "key": { "type": "string", "description": "S3 object key" }, "with_base64": { "type": "boolean", "description": "Include base64-encoded content in response" }, "isNSFWAllowed": { "type": "boolean", "description": "Whether NSFW content is permitted" } }, "required": ["type", "bucket", "key", "isNSFWAllowed"] }, "MetadataRequest": { "oneOf": [ { "$ref": "#/components/schemas/MetadataRequestExternal" }, { "$ref": "#/components/schemas/MetadataRequestUpload" }, { "$ref": "#/components/schemas/MetadataRequestBase64" }, { "$ref": "#/components/schemas/MetadataRequestS3" } ], "discriminator": { "propertyName": "type", "mapping": { "external": "#/components/schemas/MetadataRequestExternal", "upload": "#/components/schemas/MetadataRequestUpload", "base64": "#/components/schemas/MetadataRequestBase64", "s3": "#/components/schemas/MetadataRequestS3" } } }, "MetadataResponse": { "type": "object", "description": "Response from metadata extraction", "properties": { "format": { "type": "string", "description": "Detected media format (e.g., png, jpeg, gif, mp4)" }, "content_type": { "type": "string", "description": "MIME content type" }, "content_hash": { "type": "string", "description": "SHA-256 hash of content" }, "size": { "type": "integer", "description": "File size in bytes" }, "width": { "type": "integer", "description": "Image/video width in pixels" }, "height": { "type": "integer", "description": "Image/video height in pixels" }, "duration": { "type": "number", "description": "Video/audio duration in seconds" }, "placeholder": { "type": "string", "description": "BlurHash placeholder string" }, "base64": { "type": "string", "description": "Base64-encoded content (if requested)" }, "animated": { "type": "boolean", "description": "Whether the media is animated" }, "nsfw": { "type": "boolean", "description": "NSFW detection result" }, "nsfw_probability": { "type": "number", "description": "NSFW probability score (0-1)" }, "nsfw_predictions": { "type": "object", "additionalProperties": { "type": "number" }, "description": "Per-category NSFW predictions" } }, "required": ["format", "content_type", "content_hash", "size", "nsfw"] }, "ThumbnailRequestBody": { "type": "object", "description": "Request body for thumbnail generation", "properties": { "upload_filename": { "type": "string", "description": "Filename of the uploaded video" } }, "required": ["upload_filename"] }, "ThumbnailResponse": { "type": "object", "description": "Response from thumbnail generation", "properties": { "thumbnail": { "type": "string", "description": "Base64-encoded thumbnail image" }, "mime_type": { "type": "string", "description": "MIME type of thumbnail" } }, "required": ["thumbnail", "mime_type"] }, "FrameRequestUpload": { "type": "object", "description": "Frame extraction request for uploaded files", "properties": { "type": { "type": "string", "const": "upload" }, "upload_filename": { "type": "string", "description": "Filename in the uploads bucket" } }, "required": ["type", "upload_filename"] }, "FrameRequestS3": { "type": "object", "description": "Frame extraction request for S3 objects", "properties": { "type": { "type": "string", "const": "s3" }, "bucket": { "type": "string", "description": "S3 bucket name" }, "key": { "type": "string", "description": "S3 object key" } }, "required": ["type", "bucket", "key"] }, "FrameRequest": { "oneOf": [ { "$ref": "#/components/schemas/FrameRequestUpload" }, { "$ref": "#/components/schemas/FrameRequestS3" } ], "discriminator": { "propertyName": "type", "mapping": { "upload": "#/components/schemas/FrameRequestUpload", "s3": "#/components/schemas/FrameRequestS3" } } }, "ExtractedFrame": { "type": "object", "description": "Single extracted video frame", "properties": { "timestamp": { "type": "number", "description": "Frame timestamp in seconds" }, "mime_type": { "type": "string", "description": "MIME type of frame image" }, "base64": { "type": "string", "description": "Base64-encoded frame image" } }, "required": ["timestamp", "mime_type", "base64"] }, "FrameResponse": { "type": "object", "description": "Response from frame extraction", "properties": { "frames": { "type": "array", "items": { "$ref": "#/components/schemas/ExtractedFrame" }, "description": "Extracted video frames" } }, "required": ["frames"] }, "Error": { "type": "object", "description": "Error response", "properties": { "error": { "type": "string", "description": "Error message" } } } }, "parameters": { "sizeParam": { "name": "size", "in": "query", "required": false, "schema": { "$ref": "#/components/schemas/ImageSizeEnum" }, "description": "Target image size in pixels. Default: 128" }, "formatParam": { "name": "format", "in": "query", "required": false, "schema": { "$ref": "#/components/schemas/ImageFormatEnum" }, "description": "Output image format. Default: webp" }, "qualityParam": { "name": "quality", "in": "query", "required": false, "schema": { "$ref": "#/components/schemas/ImageQualityEnum" }, "description": "Image quality level. Default: high" }, "animatedParam": { "name": "animated", "in": "query", "required": false, "schema": { "type": "string", "enum": ["true", "false"] }, "description": "Whether to return animated images (GIF, APNG). Default: false" }, "widthParam": { "name": "width", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 4096 }, "description": "Target width in pixels (1-4096)" }, "heightParam": { "name": "height", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 4096 }, "description": "Target height in pixels (1-4096)" } }, "securitySchemes": { "internalKey": { "type": "http", "scheme": "bearer", "description": "Internal service authentication using Bearer token" } } } }