1472 lines
32 KiB
JSON
1472 lines
32 KiB
JSON
{
|
|
"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"
|
|
}
|
|
}
|
|
}
|
|
}
|