Developer API

The whole library is available as public JSON, so you can build it into your own tools: preroll managers, server plugins, or a script that syncs new clips to a folder on your server. This page documents the endpoints and fields. Please credit Prerolls.me and the original creators wherever you show the clips.

Overview

Everything is JSON over HTTPS, no key needed for reading. Base URL: https://www.prerolls.me. There are two ways in:

  • Static catalog files: the whole library in one file, rebuilt every time we publish. Served from Cloudflare's cache, so fetch it as often as you like.
  • Live endpoints: search and single-item lookups straight from the database. Rate-limited per IP.

Full catalog (recommended)

EndpointReturns
GET /api/v1/catalog.jsonEvery published preroll, plus platforms, categories and tags
GET /api/v1/platforms/{plex|jellyfin|emby}.jsonPrerolls made for one server
GET /api/v1/categories/{slug}.jsonPrerolls in one category
curl https://www.prerolls.me/api/v1/catalog.json

{
  "version": 1,
  "generatedAt": "2026-11-06T10:00:00.000Z",
  "count": 140,
  "platforms": [...], "categories": [...], "tags": [...],
  "prerolls": [ { ...preroll object... } ]
}

Use generatedAt or each item's updatedAt to tell when something changed.

Live search API

GET /api/v1/prerolls with any of these query parameters:

ParamExampleNotes
qnetflixMatches title, category, tags
platformplexplex, jellyfin or emby
categorystudio-logosCategory slug
tagchristmasTag slug
durationlt10lt10, 10-20, 20-30, 30plus
sortpopularnewest (default), popular, loved, shortest, az
page, limit1, 24limit is capped at 100
GET /api/v1/prerolls?platform=jellyfin&sort=popular&limit=10

{ "data": [ ... ], "page": 1, "limit": 10, "total": 30, "totalPages": 3 }

GET /api/v1/prerolls/{slug} returns one preroll, or 404.

The preroll object

{
  "id": "kYJ9gXbEky7O",
  "slug": "x-logo-emby-pre-roll",
  "title": "X Logo",
  "description": "Two metallic lines cross to form a letter in this sleek industrial video. The minimal design offers a clean and professional look for the screen.",
  "url": "https://www.prerolls.me/preroll/x-logo-emby-pre-roll",
  "platforms": [
    "emby"
  ],
  "category": {
    "slug": "glitch-tech",
    "name": "Glitch & Tech"
  },
  "tags": [],
  "source": "r2",
  "durationSeconds": 5.4,
  "width": 1920,
  "height": 1080,
  "fileSize": 3273811,
  "mime": "video/mp4",
  "thumbnail": {
    "small": "https://videos.prerolls.me/thumbs/kYJ9gXbEky7O-480.webp",
    "large": "https://videos.prerolls.me/thumbs/kYJ9gXbEky7O-960.webp"
  },
  "video": {
    "directUrl": "https://videos.prerolls.me/X%20Logo%20Emby%20Pre-roll.mp4",
    "embedUrl": null,
    "watchUrl": null,
    "youtubeId": null,
    "vimeoId": null
  },
  "download": {
    "url": "https://www.prerolls.me/download/x-logo-emby-pre-roll",
    "isDirectFile": true
  },
  "credit": null,
  "customizeUrl": "https://priyansh.net/store",
  "stats": {
    "downloads": 0,
    "likes": 0
  },
  "publishedAt": "2026-01-16T01:24:00Z",
  "updatedAt": "2026-01-16T01:24:00Z"
}
  • source is r2 (we host the MP4), youtube or vimeo.
  • video.directUrl is a plain MP4 URL for r2 items, and null otherwise.
  • credit is who made it. Please show it if you display the preroll in your app.

Downloading files

Use download.url (/download/{slug}). It counts the download, which keeps our "most downloaded" list honest, then redirects. When download.isDirectFile is true, it ends at the MP4 itself. Otherwise it goes to the creator's link or a third-party page, so check the response type before saving it as a video.

Example: sync a folder

// Node 20+: download every Jellyfin preroll we host into ./prerolls
import fs from 'node:fs';
const res = await fetch('https://www.prerolls.me/api/v1/platforms/jellyfin.json');
const { prerolls } = await res.json();
fs.mkdirSync('prerolls', { recursive: true });
for (const p of prerolls.filter((p) => p.download.isDirectFile)) {
  const file = `prerolls/${p.slug}.mp4`;
  if (fs.existsSync(file)) continue;
  const mp4 = await fetch(p.download.url);
  fs.writeFileSync(file, Buffer.from(await mp4.arrayBuffer()));
}

Admin API

Writing to the library (adding prerolls, bulk uploads, approvals) goes through /api/v1/admin/* and needs an API key created in the admin panel, sent as Authorization: Bearer <key>. Keys have scopes (read, write, upload, delete). This part isn't public.

Fair use

  • Prefer the static catalog for syncing. Poll it at most once an hour.
  • Live endpoints are limited to about 120 requests a minute per IP. You'll get 429 past that.
  • Link back to the preroll page (url) and show the credit where you can.
  • Prerolls are meant for personal media servers.