APIConstruir con MYEQ

Visión general de Production API

La API HTTP expone la misma autoridad de producción provider-neutral que usa MYEQ Studio.

Madurez API / MCP

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.

Un único ciclo

Context → Plan → Preflight → Execute → Inspect → Decide → Repair → Certify → Deliver es el modelo semántico duradero. Consulta el manifiesto vivo antes de asumir disponibilidad o estabilidad.

Planifica antes de gastar

El plan convierte intención creativa en una propuesta inspeccionable sin despachar generación pagada. Preflight comprueba accesos, referencias, capacidades y presupuesto.

curl -X POST https://myeq.pro/api/v1/production/plans \
  -H "Authorization: Bearer $MYEQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "projectId": "project-123",
    "script": "Create a 60-second vertical trailer",
    "vertical": "ai_film",
    "sourceLanguage": "en",
    "responseLanguage": "es",
    "dialogueLanguage": "es",
    "visualPromptLanguage": "en"
  }'

La ejecución es durable

La ejecución pagada queda bajo autoridad de MYEQ y no depende de que el cliente siga conectado. Consulta el job en lugar de mantener vivo el proceso llamante.

Los contratos públicos son provider-neutral

El cliente expresa intención y capacidades MYEQ, no runtimes privados ni proveedores retirados. Los detalles de implementación quedan detrás de adaptadores.

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.

FPSClase admitidaLímites físicos
24Por defecto; cada modalidad debe superar su admisiónDuración, audio y referencias dependen de la clase nativa elegida
30Solo I2V / A2V aprobados720p · 2–10 segundos enteros · 9:16 / 16:9 / 1:1 · I2V/A2V: START y/o END; A2V también exige audio de origen
60Solo I2V / A2V aprobados720p · 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'));
}
Workspace · Project · Asset · Entity · Storyboard · Plan · JobGenerado ≠ Certificado