API · v1

API de Vyclo

Envía un enlace y recibe clips verticales con subtítulos, desde tu código o desde Zapier, Make o n8n. Te avisamos con un webhook firmado cuando están listos.

Autenticación

Crea una clave en Vyclo → Ajustes → Claves de API (solo el dueño del workspace; incluida en el plan Agencia y durante la prueba gratuita). Envíala en cada petición como Authorization: Bearer vy_live_… (o en la cabecera X-Api-Key). La clave actúa sobre su workspace: los clips aparecen también en tu biblioteca y consumen minutos de tu plan como cualquier otro video.

Crear clips · POST /v1/clips

curl https://api.vyclo.studio/v1/clips \
  -H "Authorization: Bearer vy_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.youtube.com/watch?v=…",
    "rightsConfirmed": true,
    "count": 5,
    "duration": "medium",
    "captions": "twitch",
    "translateTo": "en",
    "webhookUrl": "https://tu-servidor.com/vyclo"
  }'
HTTP/1.1 202 Accepted
{ "jobId": "5f1c…", "projectId": "9a2e…", "status": "queued", "clips": [] }
CampoDescripción
urlObligatorio. Enlace https de YouTube, Google Drive, Dropbox o un MP4.
rightsConfirmedObligatorio, true: confirmas que tienes derechos sobre el video.
countNúmero de clips, de 1 a 10 (5 por defecto).
durationshort (~25 s), medium (~45 s, por defecto) o long (~75 s).
formatvertical (9:16, por defecto), square (1:1) o source (16:9).
captionsdynamic, impact, modern, neon, twitch, kick, karaoke, minimal, default o none.
cutPausesQuitar pausas largas (true por defecto).
hookTitleGancho en pantalla los primeros 3 s (true por defecto).
progressBarBarra de progreso (false por defecto).
translateToen o pt para subtítulos traducidos; omítelo para el idioma original.
projectNameNombre del proyecto en tu biblioteca (opcional).
webhookUrlhttps público al que avisamos al terminar (opcional).

Estado y clips · GET /v1/jobs/{jobId}

curl https://api.vyclo.studio/v1/jobs/5f1c… -H "Authorization: Bearer vy_live_…"

{
  "jobId": "5f1c…", "projectId": "9a2e…",
  "status": "rendering",          // queued · importing · transcribing · selecting · rendering · completed · failed
  "clips": [                      // aparecen mientras se renderizan
    { "id": "…", "title": "¿Cuántas veces aparece la letra R…?", "score": 9, "reason": "abre con una pregunta",
      "startSeconds": 913.1, "endSeconds": 950.7, "durationSeconds": 35.2,
      "videoUrl": "https://…", "posterUrl": "https://…", "subtitlesUrl": "https://…" }
  ]
}

Los enlaces de video, miniatura y subtítulos (SRT) son firmados y caducan a las 2 horas: vuelve a pedir el estado para obtener enlaces nuevos. También puedes listar los clips de un proyecto con GET /v1/projects/{projectId}/clips y ver tu consumo con GET /v1/usage.

Webhooks

Si envías webhookUrl, hacemos un POST con el evento clips.ready o clips.failed (hasta 3 intentos). Verifica la firma con el secreto whsec_… que se muestra al crear la clave: es un HMAC-SHA256 de t + "." + cuerpo.

POST https://tu-servidor.com/vyclo
Vyclo-Signature: t=1790000000,v1=5d2c…

{ "event": "clips.ready", "jobId": "5f1c…", "projectId": "9a2e…", "clipCount": 5,
  "statusUrl": "https://api.vyclo.studio/v1/jobs/5f1c…", "sentAt": "2026-09-28T20:00:00Z" }

Verificar la firma · Node.js

import crypto from "node:crypto";

function verify(rawBody, header, secret) {           // secret: whsec_…
  const { t, v1 } = Object.fromEntries(header.split(",").map((part) => part.split("=")));
  const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300;
  return fresh && crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
}

Python

import hashlib, hmac, time

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(part.split("=", 1) for part in header.split(","))
    expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
    return abs(time.time() - int(parts["t"])) < 300 and hmac.compare_digest(parts["v1"], expected)

Límites y errores

  • 120 peticiones por minuto por clave; si te pasas, 429 con Retry-After.
  • Importaciones por URL: hasta 20 al día por workspace.
  • 400 datos no válidos (el mensaje dice cuál), 401 clave ausente o revocada, 403 sin permiso.