Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/coah80/yoink/llms.txt

Use this file to discover all available pages before exploring further.

The bot API is an internal interface consumed by the Yoink Discord bot. All endpoints require a Bearer token matching the BOT_SECRET environment variable. Requests without a valid token receive 401 Unauthorized. Unlike the web download endpoints, all bot jobs are fully asynchronous — every request returns a jobId immediately. Poll GET /api/bot/status/{jobId} to track progress and retrieve the downloadToken when the job completes. Tokens expire after 5 minutes (BotDownloadExpiry). Playlist tokens last longer; they use the same 12-hour expiry as the web playlist API.
If BOT_SECRET is not set, checkBotAuth always returns false and every bot request receives 401 Unauthorized. The bot API will be completely non-functional until BOT_SECRET is configured. Always set this variable in production.

Authentication

Every request to /api/bot/* must include the following header:
Authorization: Bearer <BOT_SECRET>

POST /api/bot/download

Downloads a single video or audio track from any yt-dlp-supported URL and makes the result available via a short-lived download token.
POST /api/bot/download
Authorization: Bearer <BOT_SECRET>
Content-Type: application/json

Body Fields

url
string
required
URL of the media to download.
format
string
default:"video"
video or audio.
quality
string
default:"1080p"
Target resolution. One of 2160p, 1440p, 1080p, 720p, 480p, 360p.
container
string
default:"mp4"
Video container. One of mp4, webm, mkv, mov.
audioFormat
string
default:"mp3"
Audio format when format=audio. One of mp3, m4a, opus, wav, flac.
playlist
boolean
default:"false"
Download as playlist. For large playlist jobs prefer POST /api/bot/download-playlist which returns richer per-video status.

Response

{ "jobId": "550e8400-e29b-41d4-a716-446655440000" }

curl Example

curl -s -X POST https://yoink.example.com/api/bot/download \
  -H "Authorization: Bearer ${BOT_SECRET}" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ","format":"video","quality":"720p"}'

POST /api/bot/download-playlist

Downloads an entire playlist asynchronously, zips the results, and stores the archive for retrieval.
POST /api/bot/download-playlist
Authorization: Bearer <BOT_SECRET>
Content-Type: application/json

Body Fields

url
string
required
URL of the playlist.
format
string
default:"video"
video or audio.
quality
string
default:"1080p"
Target resolution for video downloads.
container
string
default:"mp4"
Video container format.
audioFormat
string
default:"mp3"
Audio format when format=audio.
audioBitrate
string
default:"320"
Audio bitrate in kbps. One of 64, 96, 128, 192, 256, 320.
resumeFrom
integer
default:"1"
1-based playlist index to start from. Use for chunked processing of large playlists.

Response

{ "jobId": "550e8400-e29b-41d4-a716-446655440000" }

POST /api/bot/convert

Downloads a file from a Discord CDN URL and converts it to the specified format.
POST /api/bot/convert
Authorization: Bearer <BOT_SECRET>
Content-Type: application/json
The url field for /api/bot/convert and /api/bot/compress only accepts Discord CDN URLs (cdn.discordapp.com or media.discordapp.net). Any other hostname returns a 400 error: "only Discord CDN URLs are accepted".

Body Fields

url
string
required
Discord CDN URL of the file to convert (e.g. https://cdn.discordapp.com/attachments/...).
format
string
default:"mp4"
Target format. Video: mp4, webm, mkv, mov. Audio: mp3, m4a, opus, wav, flac.

Response

{ "jobId": "550e8400-e29b-41d4-a716-446655440000" }

curl Example

curl -s -X POST https://yoink.example.com/api/bot/convert \
  -H "Authorization: Bearer ${BOT_SECRET}" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://cdn.discordapp.com/attachments/123/456/video.mov","format":"mp4"}'

POST /api/bot/compress

Compresses a video to a target file size. The source can be a Discord CDN URL or a downloadToken from a previous bot job (e.g. chain a download then compress it).
POST /api/bot/compress
Authorization: Bearer <BOT_SECRET>
Content-Type: application/json
When providing url, only Discord CDN URLs are accepted (cdn.discordapp.com / media.discordapp.net). You must supply either url or downloadToken — omitting both returns a 400 error.

Body Fields

url
string
Discord CDN URL of the video to compress. Mutually exclusive with downloadToken.
downloadToken
string
Token from a previous bot job. Allows chaining: download a video, then compress the result without re-downloading.
targetSize
string
default:"25"
Target output size in megabytes. Discord’s default file limit is 25 MB (Nitro: 500 MB).
preset
string
default:"fast"
Encoding speed preset. One of fast, balanced, quality.

Response

{ "jobId": "550e8400-e29b-41d4-a716-446655440000" }

curl Example

curl -s -X POST https://yoink.example.com/api/bot/compress \
  -H "Authorization: Bearer ${BOT_SECRET}" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://cdn.discordapp.com/attachments/123/456/big_video.mp4","targetSize":"25","preset":"fast"}'

GET /api/bot/status/

Returns the current state of any bot job (download, playlist, convert, or compress).
GET /api/bot/status/{jobId}
Authorization: Bearer <BOT_SECRET>

Response Fields

status
string
Job state: starting, downloading, processing, complete, error.
progress
number
Completion percentage, 0–100.
message
string
Human-readable status message.
error
string
Error message. Present when status=error.
fileName
string
Output filename (present when status=complete).
fileSize
number
Output file size in bytes (present when status=complete).
downloadToken
string
Short-lived token for GET /api/bot/download/{token} (present when status=complete).
speed
string
Download speed string (e.g. "5.2MiB/s"), present during active downloads.
eta
string
Estimated time remaining (e.g. "00:01:23"), present during active downloads.
videosCompleted
number
For playlist jobs: number of videos successfully downloaded so far.
totalVideos
number
For playlist jobs: total videos in the playlist.
startVideo
number
For playlist jobs: 1-based index of the first video downloaded in this run (reflects resumeFrom).
failedVideos
array
For playlist jobs: array of { num, title, reason } objects for failed videos.

curl Example

curl -s https://yoink.example.com/api/bot/status/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer ${BOT_SECRET}"

GET /api/bot/download/

Streams the completed file. The token comes from the downloadToken field in the status response. No authentication header is required for this endpoint.
GET /api/bot/download/{token}
Bot download tokens expire 5 minutes after creation. After expiry the file is deleted and this endpoint returns 404.

Response

Streams the binary file with Content-Type and Content-Disposition: attachment headers appropriate for the file type.

curl Example

curl -L -o output.mp4 https://yoink.example.com/api/bot/download/your_token_here

GET /api/download/

Serves a simple HTML download page for the file identified by token. This is used as a fallback link in Discord messages — when a file is too large to attach directly, the bot sends this URL so the user can click it in a browser to trigger the download.
GET /api/download/{token}
No authentication is required. If the token has expired or the file no longer exists, a 404 HTML page is returned. Otherwise the browser receives a page that automatically triggers the download via a hidden <iframe> within 2 seconds and displays a progress spinner.
This endpoint is intentionally unauthenticated so that Discord users who receive the link can download their file without needing bot credentials.

Complete Bot Job Flow

#!/usr/bin/env bash
# Download a video and wait for the result

BASE="https://yoink.example.com"

# 1. Start the job
JOB_ID=$(curl -s -X POST "${BASE}/api/bot/download" \
  -H "Authorization: Bearer ${BOT_SECRET}" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://www.youtube.com/watch?v=dQw4w9WgXcQ","format":"video","quality":"720p"}' \
  | jq -r .jobId)

echo "Job started: ${JOB_ID}"

# 2. Poll until complete
while true; do
  RESP=$(curl -s "${BASE}/api/bot/status/${JOB_ID}" \
    -H "Authorization: Bearer ${BOT_SECRET}")
  STATUS=$(echo "$RESP" | jq -r .status)
  MSG=$(echo "$RESP" | jq -r .message)
  echo "  [${STATUS}] ${MSG}"

  if [ "$STATUS" = "complete" ]; then
    TOKEN=$(echo "$RESP" | jq -r .downloadToken)
    FILENAME=$(echo "$RESP" | jq -r .fileName)
    FILE_SIZE=$(echo "$RESP" | jq -r .fileSize)
    echo "Ready: ${FILENAME} ($(( FILE_SIZE / 1024 / 1024 )) MB) — token: ${TOKEN}"
    break
  fi

  if [ "$STATUS" = "error" ]; then
    echo "Job failed: ${MSG}"
    exit 1
  fi

  sleep 2
done

# 3. Download (no auth needed)
curl -L -o "${FILENAME}" "${BASE}/api/bot/download/${TOKEN}"
echo "Saved: ${FILENAME}"

Build docs developers (and LLMs) love