API para desarrolladores
Una API REST para gestionar tu videoteca y automatizar tu flujo de trabajo. Todas las respuestas son JSON. URL base:
https://otakuga.com/api/v1Introducción
La API de Otakuga te permite subir, listar y consultar tus vídeos mediante peticiones HTTP, y reaccionar a eventos con webhooks. Es una función del plan Scale.
Todos los endpoints cuelgan de https://otakuga.com/api/v1, aceptan y devuelven JSON, y requieren autenticación por clave (salvo el proxy de subida, que usa un token temporal). El contenido de vídeo se sirve por streaming HLS a través de nuestra red CDN; la API no expone detalles de la infraestructura subyacente.
Autenticación
Crea una clave de API en el panel, en Ajustes → Claves de API. La clave se muestra una sola vez al crearla (formato sv_live_…); guárdala en un lugar seguro.
Envíala en la cabecera Authorization como Bearer token en cada petición:
curl https://otakuga.com/api/v1/videos \
-H "Authorization: Bearer sv_live_tu_clave_aqui"Trata la clave como un secreto de servidor. Da acceso a todos los vídeos de tu cuenta: úsala solo desde tu backend, nunca la incrustes en un navegador ni en una app cliente.
Errores
Los errores devuelven un código HTTP y un cuerpo JSON con el campo error:
{ "error": "No autorizado" }401— clave ausente o inválida.402— cuota de plan agotada o ancho de banda sin crédito.403— tu plan no incluye la API (requiere Scale).404— recurso no encontrado.500— error interno; incluye unarefpara soporte.
El objeto vídeo
{
"id": "cmr...", // identificador del vídeo
"title": "Mi vídeo",
"description": null,
"status": "READY", // ver estados abajo
"durationSeconds": 128,
"sizeBytes": 48213344,
"playCount": 57,
"collectionId": null,
"createdAt": "2026-07-18T12:00:00.000Z"
}El campo status puede ser: CREATED, UPLOADING, UPLOADED, PROCESSING, READY (listo para reproducir), FAILED o DELETED.
Listar vídeos
/videosDevuelve tus vídeos, del más reciente al más antiguo, con paginación por cursor. Parámetros de consulta (todos opcionales):
limit— número de resultados (1–100, por defecto 50).cursor—iddel último vídeo de la página anterior.status— filtra por estado (p. ej.READY).
curl "https://otakuga.com/api/v1/videos?limit=20&status=READY" \
-H "Authorization: Bearer sv_live_…"{
"videos": [ { "id": "cmr…", "title": "Mi vídeo", "status": "READY", … } ],
"nextCursor": "cmr…" // null si no hay más páginas
}Crear un vídeo
/videosCrea el registro del vídeo y devuelve, además del objeto, un descriptor de subida que usarás en el siguiente paso. Cuerpo (JSON):
title— título del vídeo (opcional).collectionId— id de una colección para organizarlo (opcional).
curl -X POST https://otakuga.com/api/v1/videos \
-H "Authorization: Bearer sv_live_…" \
-H "Content-Type: application/json" \
-d '{ "title": "Mi vídeo" }'{
"video": { "id": "cmr…", "status": "UPLOADING", … },
"upload": {
"protocol": "tus",
"endpoint": "https://otakuga.com/api/v1/upload",
"headers": { "X-Upload-Token": "…" },
"metadata": { "filetype": "video/mp4", "title": "Mi vídeo" }
}
}Subir el archivo
La subida usa el protocolo TUS (resumible), contra el endpoint y con los headers que devolvió el paso anterior. Los bytes se transmiten a través de nuestro servidor sin almacenarse en él. Ejemplo en Node con tus-js-client:
import * as tus from "tus-js-client";
import fs from "node:fs";
// 1) Crear el vídeo (paso anterior) → { video, upload }
const res = await fetch("https://otakuga.com/api/v1/videos", {
method: "POST",
headers: { Authorization: "Bearer sv_live_…", "Content-Type": "application/json" },
body: JSON.stringify({ title: "Mi vídeo" }),
});
const { video, upload } = await res.json();
// 2) Subir el archivo al endpoint devuelto
const path = "mi-video.mp4";
new tus.Upload(fs.createReadStream(path), {
endpoint: upload.endpoint,
headers: upload.headers, // incluye X-Upload-Token
uploadSize: fs.statSync(path).size,
metadata: upload.metadata,
chunkSize: 50 * 1024 * 1024, // 50 MB por trozo (recomendado)
onSuccess: () => console.log("Subido:", video.id),
onError: (err) => console.error(err),
}).start();Cuando termine la subida, el vídeo pasa por PROCESSING y luego a READY. Suscríbete al webhook video.ready (más abajo) para enterarte sin sondear.
Obtener un vídeo
/videos/:idcurl https://otakuga.com/api/v1/videos/cmr… \
-H "Authorization: Bearer sv_live_…"{ "video": { "id": "cmr…", "status": "READY", … } }Un id de otro tenant devuelve 404: cada clave solo accede a los vídeos de su propia cuenta.
Webhooks
Configura webhooks salientes en el panel (Ajustes → Webhooks) para que te avisemos cuando ocurra un evento. Eventos disponibles:
video.ready— un vídeo terminó de procesarse y está listo.lead.captured— un espectador dejó sus datos en el reproductor.
Enviamos un POST a tu URL con este cuerpo, y las cabeceras X-Nubiux-Event y X-Nubiux-Signature:
{
"event": "video.ready",
"at": "2026-07-18T12:00:00.000Z",
"data": { … }
}Verificar la firma
La firma es un HMAC-SHA256 del cuerpo crudo con el secreto del webhook (que se muestra una vez al crearlo). Compárala en tiempo constante:
import crypto from "node:crypto";
function verificar(cuerpoCrudo, firma, secreto) {
const esperada = crypto.createHmac("sha256", secreto)
.update(cuerpoCrudo).digest("hex");
return crypto.timingSafeEqual(
Buffer.from(firma), Buffer.from(esperada)
);
}¿Dudas o te falta algún endpoint? Escríbenos a soporte@otakuga.com. Consulta también los Términos.