TrollflixDevelopers
Videos

Upload a video

Publish a video to your channel, now or at a scheduled time.

POST https://uploads.backend.trollflix.com/api/php/developer/upload_video

Uploads one video to the channel that owns the API key. The request is multipart/form-data; only file is required.

The upload goes through exactly the same checks as an upload from the Trollflix app or website, so anything the uploader would reject, this endpoint rejects with the same error code.

Headers

Prop

Type

Body

The video

Prop

Type

Text and category

Prop

Type

Labels

Prop

Type

Thumbnail

Send at most one of these. Without either, Trollflix picks a frame for you. See the thumbnails guide.

Prop

Type

Publishing

Prop

Type

Presentation

Prop

Type

Example

curl -X POST "https://uploads.backend.trollflix.com/api/php/developer/upload_video" \
  -H "Authorization: Bearer $TROLLFLIX_API_KEY" \
  -F "[email protected]" \
  -F "caption=Me explaining my code to the rubber duck #programming" \
  -F "super_category_id=1" \
  -F "thumbnail_time=00:00:02" \
  -F "ai_summary_of_content=A developer talks to a rubber duck on a desk, the duck slowly turns away." \
  -F "upload_token=7b0e1f3a-2c4d-4e5f-8a9b-0c1d2e3f4a5b"
upload.mjs (Node.js 20+)
import { openAsBlob } from "node:fs";
import { randomUUID } from "node:crypto";

const form = new FormData();
form.append("file", await openAsBlob("meme.mp4"), "meme.mp4");
form.append("caption", "Me explaining my code to the rubber duck #programming");
form.append("super_category_id", "1");
form.append("thumbnail_time", "00:00:02");
form.append(
  "ai_summary_of_content",
  "A developer talks to a rubber duck on a desk, the duck slowly turns away.",
);
form.append("upload_token", randomUUID());

const response = await fetch(
  "https://uploads.backend.trollflix.com/api/php/developer/upload_video",
  {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.TROLLFLIX_API_KEY}` },
    body: form,
  },
);

const result = await response.json();
if (result.success !== true) {
  throw new Error(`Upload failed: ${result.error_message_code}`);
}
console.log(`https://www.trollflix.com/meme/${result.slug_url}`);
upload.py
import os
import uuid
import requests

with open("meme.mp4", "rb") as video:
    response = requests.post(
        "https://uploads.backend.trollflix.com/api/php/developer/upload_video",
        headers={"Authorization": f"Bearer {os.environ['TROLLFLIX_API_KEY']}"},
        files={"file": ("meme.mp4", video, "video/mp4")},
        data={
            "caption": "Me explaining my code to the rubber duck #programming",
            "super_category_id": "1",
            "thumbnail_time": "00:00:02",
            "ai_summary_of_content": "A developer talks to a rubber duck on a desk, the duck slowly turns away.",
            "upload_token": str(uuid.uuid4()),
        },
        timeout=600,
    )

result = response.json()
if result.get("success") is not True:
    raise RuntimeError(f"Upload failed: {result.get('error_message_code')}")
print(f"https://www.trollflix.com/meme/{result['slug_url']}")

Response

{
  "success": true,
  "id": 18240,
  "content_id": 18301,
  "content_uuid": "0d6c1a0e-3c55-4c41-9a51-3f1f0f8f4a52",
  "media_name": "a1b2c3d4e5f60718293a4b5c6d7e8f90.mp4",
  "message_code": "content_upload_success",
  "scheduled_publish_at_unix": null,
  "ui_limit_failure_translation_key": "content_upload_limit_failure",
  "is_limit_activated": false,
  "limit_reset_time_unix": null,
  "limit_amount": 4,
  "slug_url": "me-explaining-my-code-to-the-rubber-duck-programming"
}
{
  "success": false,
  "error_message_code": "content_video_duration_invalid"
}
{
  "success": false,
  "error_message_code": "api_key_invalid"
}

Prop

Type

Not live instantly

A successful response means the meme exists and is processing: moderation, transcoding and thumbnails run in the background and usually finish within a few minutes. A video that fails moderation is never shown publicly.

Errors

The most common rejections for this endpoint. The full list is in Errors.

error_message_codeWhat to do
file_not_foundSend the video in a form field named file.
content_file_invalid_formatUse one of the supported video formats.
content_video_duration_invalidTrim the video to 2 to 120 seconds.
content_upload_limit_failureYou reached today's upload limit. Wait for limit_reset_time_unix.
content_category_invalidUse an ID from the category list.