Tasks

GET /api/v1/tasks/{id}, /tasks/{id}/events und /tasks – Status eines Tasks prüfen, Fortschritt streamen, Ergebnis herunterladen, frühere Tasks auflisten.

Einen Task abrufen

GET https://videoupscaler.co/api/v1/tasks/{id}

Gibt den Task mit seinem aktuellen Status zurück. Frage ihn alle 5–10 Sekunden ab, solange er queued oder processing ist. Längere Videos und höhere Auflösungen brauchen mehr Zeit.

curl https://videoupscaler.co/api/v1/tasks/0b6f3c1e-8a52-5d1e-9c43-3f1d2e7a9b10 \
  -H "Authorization: Bearer $VIDEOUPSCALER_API_KEY"
{
  "id": "0b6f3c1e-8a52-5d1e-9c43-3f1d2e7a9b10",
  "status": "completed",
  "resolution": "2k",
  "video_url": "https://example.com/clip.mp4",
  "duration_seconds": 12.4,
  "processed_seconds": 12.4,
  "credits_charged": 26,
  "watermark": false,
  "output_url": "https://…/clip_upscaled.mp4",
  "thumbnail_url": "https://…/clip_first_frame.jpg",
  "error": null,
  "created_at": "2026-09-30T08:00:00.000Z",
  "updated_at": "2026-09-30T08:03:41.000Z"
}

Ein Task, der nicht existiert oder zu einem anderen Konto gehört, liefert 404 not_found.

Polling-Beispiel

async function waitForTask(id) {
  while (true) {
    const res = await fetch(`https://videoupscaler.co/api/v1/tasks/${id}`, {
      headers: { Authorization: `Bearer ${process.env.VIDEOUPSCALER_API_KEY}` },
    });
    const task = await res.json();
    if (task.status === 'completed') return task.output_url;
    if (task.status === 'failed') throw new Error(task.error);
    await new Promise((r) => setTimeout(r, 8000));
  }
}

Task-Events streamen

GET https://videoupscaler.co/api/v1/tasks/{id}/events

Statt zu pollen, kannst du eine einzige Verbindung offen halten und den Fortschritt des Tasks als Server-Sent Events empfangen. Die Anfrage antwortet mit einer 302-Weiterleitung auf eine signierte Stream-URL; SSE-Clients folgen ihr automatisch (bei curl ergänzt du -L). Die signierte URL gewährt den Zugriff bereits, dein API-Schlüssel wird also nicht an sie gesendet.

EventDatenWann
status{"id": "…", "status": "queued"}Der Job wartet auf eine GPU (queued) oder läuft (processing). Wird bei jeder Änderung gesendet.
completedDer vollständige TaskDas Ergebnis ist fertig. Danach wird der Stream geschlossen.
failedDer vollständige TaskDie Verarbeitung ist fehlgeschlagen und die Credits wurden erstattet. Danach wird der Stream geschlossen.
timeout{"id": "…"}Der Stream wird nach 10 Minuten geschlossen. Öffne /events erneut, wenn der Task noch läuft.

Die Daten von completed und failed entsprechen exakt dem, was GET /tasks/{id} zurückgibt. Öffnest du den Stream für einen bereits abgeschlossenen Task, wird das entsprechende Event sofort gesendet.

curl -N -L https://videoupscaler.co/api/v1/tasks/TASK_ID/events \
  -H "Authorization: Bearer $VIDEOUPSCALER_API_KEY"
event: status
data: {"id":"0b6f3c1e-…","status":"queued"}

event: status
data: {"id":"0b6f3c1e-…","status":"processing"}

event: completed
data: {"id":"0b6f3c1e-…","status":"completed","output_url":"https://…","…":"…"}
// npm install eventsource
import { EventSource } from 'eventsource';

const events = new EventSource(`https://videoupscaler.co/api/v1/tasks/${taskId}/events`, {
  fetch: (url, init) =>
    fetch(url, {
      ...init,
      headers: { ...init.headers, Authorization: `Bearer ${process.env.VIDEOUPSCALER_API_KEY}` },
    }),
});
events.addEventListener('status', (e) => console.log(JSON.parse(e.data).status));
events.addEventListener('completed', (e) => {
  console.log('done:', JSON.parse(e.data).output_url);
  events.close();
});
events.addEventListener('failed', (e) => {
  console.error(JSON.parse(e.data).error);
  events.close();
});
# pip install httpx httpx-sse
import json, os, httpx
from httpx_sse import connect_sse

headers = {"Authorization": f"Bearer {os.environ['VIDEOUPSCALER_API_KEY']}"}
url = f"https://videoupscaler.co/api/v1/tasks/{task_id}/events"
with httpx.Client(follow_redirects=True, timeout=None) as client:
    with connect_sse(client, "GET", url, headers=headers) as source:
        for event in source.iter_sse():
            task = json.loads(event.data)
            print(event.event, task["status"])
            if event.event in ("completed", "failed", "timeout"):
                break

Polling über GET /tasks/{id} liefert dasselbe Ergebnis – nimm einfach das, was besser zu deinem Code passt.

Tasks auflisten

GET https://videoupscaler.co/api/v1/tasks?limit=20&page=1
QueryStandardBeschreibung
limit20Tasks pro Seite, 1–100
page1Seitennummer, beginnend bei 1

Gibt die Tasks sortiert nach Erstellung zurück, neueste zuerst. Die Liste enthält auch Tasks, die auf der Website erstellt wurden.

{
  "data": [{ "id": "…", "status": "completed", "…": "…" }],
  "page": 1,
  "limit": 20,
  "total": 42,
  "has_more": true
}

Das Task-Objekt

FeldTypBeschreibung
idstringTask-ID
statusstringqueued, processing, completed oder failed
resolutionstring1080p, 2k oder 4k
video_urlstringDas von dir gesendete Video
duration_secondsnumberLänge des Eingabevideos, aus der Datei ausgelesen
processed_secondsnumberWie viele Sekunden hochskaliert werden. Bei API-Tasks gleich duration_seconds; kürzer nur bei Tasks, die auf der Website erstellt wurden, als das Konto noch kostenlos war.
credits_chargedintegerFür diesen Task abgebuchte Credits (werden bei einem Fehlschlag erstattet)
watermarkbooleanOb das Ergebnis ein Wasserzeichen trägt. Bei API-Tasks immer false; true nur bei Tasks, die auf der Website erstellt wurden, als das Konto noch kostenlos war.
output_urlstring | nullDas hochskalierte Video, sobald completed
thumbnail_urlstring | nullErstes Frame des Ergebnisses, sobald completed
errorstring | nullGrund für den Fehlschlag, wenn failed
created_atstringZeitpunkt im ISO-8601-Format
updated_atstringZeitpunkt im ISO-8601-Format

Lade output_url bald nach Abschluss des Tasks herunter und bewahre eine eigene Kopie auf. Verlass dich nicht darauf, dass die Datei dauerhaft gespeichert bleibt.