Mapa de referencia de Production API
Orientación humana de la superficie canónica. La referencia generada y OpenAPI siguen siendo la autoridad exacta de máquina.
La documentación pública se puede compartir, pero la disponibilidad de capacidades API y MCP la gobiernan el manifiesto vivo y el acceso de la cuenta. Foundation o experimental no implican estabilidad.
| Método | Endpoint | Autoridad | Propósito |
|---|---|---|---|
| GET | /api/v1/product/manifest | read | Verdad y madurez del producto |
| GET | /api/v1/openapi | read | Contrato API legible por máquina |
| GET | /api/v1/production/capabilities | read | Descubrir capacidades de producción disponibles |
| GET | /api/v1/production/verticals | read | Listar recetas de producción |
| POST | /api/v1/production/plans | plan | Compilar un plan de producción sin gasto |
| POST | /api/v1/production/plans/:planId/preflight | read | Validar preparación antes de ejecutar |
| POST | /api/v1/production/plans/:planId/storyboard/apply | mutate | Aplicar un Storyboard aprobado |
| POST | /api/v1/production/plans/:planId/steps/:stepId/execute | spend | Ejecutar un paso confirmado del plan |
| POST | /api/v1/production/plans/:planId/generate | spend | Iniciar producción durable confirmada |
| GET | /api/v1/production/jobs/:jobId | read | Consultar el estado durable del job |
| GET | /api/v1/production/plans/:planId/ledger | read | Consultar el ledger de ejecución |
| POST | /api/v1/production/snapshots/generate-scene | spend | Generar una escena confirmada con sus FPS admitidos |
| POST | /api/v1/production/snapshots/preflight-scene | read | Comprobar FPS y coste exactos de una escena sin gastar |
Usa el contrato generado para los campos exactos
Esta página explica intención y autoridad. Para schemas exactos y operaciones publicadas usa /api/v1/docs y /api/v1/openapi.
Trata los errores como estado, no como prosa
Maneja códigos de error y estados HTTP: autenticación, acceso prohibido, projectId inválido, idempotencia ausente, créditos insuficientes, blockers de preflight, rate limit y fallos de infraestructura.
Reintenta lecturas con criterio
El transporte distingue fallos de lectura potencialmente reintentables de operaciones que nunca deben repetirse a ciegas.
24, 30 y 60 FPS en Studio, API y MCP
Las tres interfaces usan la misma instantánea confirmada de la escena y la misma admisión. Se conservan los FPS solicitados; no hay cambio automático a 24. La disponibilidad depende del worker aprobado y de la escena exacta.
Lienzos START/END: 704×1280, 1280×704 o 960×960. I2V admite audio generado o sin audio; A2V exige audio de origen autorizado y conserva el desplazamiento seleccionado. Esta tabla no habilita FPS altos para ingredientes ni V2V. La semilla es un entero entre 0 y 2147483647. I2V y A2V admiten END sin START a 24, 30 y 60 FPS solo si el servicio desplegado lo autoriza expresamente. END guía el último fotograma; el inicio se genera desde el prompt. Deja start vacío y conserva la imagen en end. Esto no garantiza píxeles idénticos ni invierte el vídeo. A2V siempre necesita audio de origen autorizado y al menos una imagen START o END; el audio solo no está admitido.
| FPS | Clase admitida | Límites físicos |
|---|---|---|
| 24 | Por defecto; cada modalidad debe superar su admisión | Duración, audio y referencias dependen de la clase nativa elegida |
| 30 | Solo I2V / A2V aprobados | 720p · 2–10 segundos enteros · 9:16 / 16:9 / 1:1 · I2V/A2V: START y/o END; A2V también exige audio de origen |
| 60 | Solo I2V / A2V aprobados | 720p · 2–10 segundos enteros · 9:16 / 16:9 / 1:1 · I2V/A2V: START y/o END; A2V también exige audio de origen |
Guardar, revisar el precio y confirmar una escena
Crea o lee el proyecto autorizado y guarda la escena con PATCH expectedVersion. Envía la misma snapshot y targetSceneId a /api/v1/production/snapshots/preflight-scene. Revisa data.ready, issues y estimatedCredits; no crea trabajos ni reserva créditos. Genera mediante /api/v1/production/snapshots/generate-scene con confirm=true e Idempotency-Key estable. Consulta el jobId devuelto. MCP usa myeq.video.preflight_scene y myeq.video.generate_scene con la misma snapshot; el envío pagado no se reintenta automáticamente. Los ajustes de escena prevalecen sobre los globales; conserva los sceneContracts confirmados que correspondan.
Las rutas antiguas /video/start, /video/create, /video/create-job y /video/preflight están retiradas: por defecto/24 devuelve 410; 30/60 exige migrar a snapshot con 422. 25/48/50 no están admitidos. Un fallo de preflight no cambia los FPS ni cobra créditos. Una comprobación correcta no reserva disponibilidad ni saldo.
const base = process.env.MYEQ_BASE_URL || 'https://myeq.pro';
const headers = { Authorization: 'Bearer ' + process.env.MYEQ_API_KEY, 'Content-Type': 'application/json' };
async function api(path, method, body, extra = {}) {
const response = await fetch(base + path, { method, headers: { ...headers, ...extra },
...(body === undefined ? {} : { body: JSON.stringify(body) }) });
const value = await response.json();
if (!response.ok) throw new Error(JSON.stringify(value));
return value;
}
const project = await api('/api/v1/projects', 'POST', { title: '60 FPS', aspectRatio: '9:16', duration: 4 });
const sourceAudioUrl = process.env.SOURCE_AUDIO_URL;
const generationInputs = { videoProvider: 'myeq_v2', videoModelSelection: 'myeq_v2',
inputModality: sourceAudioUrl ? 'audio_to_video' : 'image_to_video', durationSeconds: 4,
fps: 60, outputResolution: '720p', includeAudio: Boolean(sourceAudioUrl), seed: 12345,
...(sourceAudioUrl ? { sourceAudioUrl, sourceAudioStartTime: 0 } : {}) };
const scene = { id: 'scene-1', prompt: 'A slow camera move. Preserve the subject.',
settings: { fps: 60, durationSeconds: 4 },
start: process.env.START_URL ? [{ name: 'START', url: process.env.START_URL }] : [],
end: process.env.END_URL ? [{ name: 'END', url: process.env.END_URL }] : [], context: [], avatar: [] };
const snapshot = { id: crypto.randomUUID(), version: 1, projectId: project.id,
ownerId: project.ownerUserId, sourceEditorStateVersion: project.version + 1,
createdAt: new Date().toISOString(), projectTitle: project.title,
aspectRatio: '9:16', resolution: '720p', durationSeconds: 4, fps: 60,
generationInputs, scenes: [scene], avatars: [], assetsSummary: [],
sourceAudio: sourceAudioUrl ? { url: sourceAudioUrl, durationSeconds: null } : null, provenance: { source: 'ui' } };
await api('/api/v1/projects/' + project.id, 'PATCH', { expectedVersion: project.version,
editorState: { ...project.editorState, generationInputs,
sceneStoryboard: { scenes: [scene] }, productionSnapshot: snapshot } });
const input = { snapshot, targetSceneId: scene.id };
const quote = await api('/api/v1/production/snapshots/preflight-scene', 'POST', input);
console.log(quote);
if (quote.data?.ready && process.env.CONFIRM_PAID === 'true') {
const idempotencyKey = process.env.SAVED_IDEMPOTENCY_KEY;
if (!idempotencyKey) throw new Error('Persist one stable key before submitting');
const result = await api('/api/v1/production/snapshots/generate-scene', 'POST',
{ ...input, confirm: true }, { 'Idempotency-Key': idempotencyKey });
console.log(result);
const jobId = result.data?.pendingTake?.orchestrationJobId || result.data?.asset?.metadata?.jobId;
if (jobId) console.log(await api('/api/v1/production/jobs/' + encodeURIComponent(jobId), 'GET'));
}