APIBuild with MYEQ

Production API overview

The HTTP API exposes the same provider-neutral production authority used by MYEQ Studio.

API / MCP maturity

The public documentation is shareable, but API and MCP capability availability is governed by the live product manifest and account access. Foundation or experimental operations are not stability promises.

One lifecycle

Context → Plan → Preflight → Execute → Inspect → Decide → Repair → Certify → Deliver is the long-lived semantic model. Not every stage is currently stable; read the live product manifest before assuming availability.

Plan before spending

Planning compiles creative intent into an inspectable proposal. It should not dispatch paid generation. Preflight then verifies access, references, capabilities and budget.

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"
  }'

Execution is durable

Paid execution returns durable authority owned by MYEQ. A client disconnect must not cancel or duplicate accepted work. Read job status instead of depending on the caller process staying alive.

Public contracts are provider-neutral

Clients choose production intent and MYEQ capabilities, not private deployment runtimes or retired provider names. Implementation details stay behind adapters.

24, 30 and 60 FPS in Studio, API and MCP

Use the same committed scene snapshot and exact admission across all three interfaces. Requested FPS is preserved; there is no automatic fallback to 24 FPS. Availability depends on the approved worker and the exact scene.

START/END canvases: 704×1280, 1280×704 or 960×960. I2V accepts generated audio or no audio; A2V requires authorized source audio and preserves its selected offset. Ingredients and V2V do not gain high FPS support from this table. Seeds are integers from 0 to 2147483647. I2V and A2V support END without START at 24, 30 and 60 FPS only when the deployed service explicitly admits it. END guides the final frame; the beginning is generated from the prompt. Leave start empty and keep the image in end. This does not promise identical pixels or reverse the video. A2V always needs authorized source audio and at least one START or END image; audio alone is not admitted.

FPSAdmitted classPhysical limits
24Default; selected modality must pass its own admissionDuration, audio and references depend on the selected native class
30Approved I2V / A2V only720p · 2–10 whole seconds · 9:16 / 16:9 / 1:1 · I2V/A2V: START and/or END; A2V also requires source audio
60Approved I2V / A2V only720p · 2–10 whole seconds · 9:16 / 16:9 / 1:1 · I2V/A2V: START and/or END; A2V also requires source audio

Save, preflight the quote, then confirm one scene

Create or read the authorized project, commit the scene with PATCH expectedVersion, then send the same snapshot and targetSceneId to /api/v1/production/snapshots/preflight-scene. Inspect data.ready, issues and estimatedCredits; this creates no job or credit reservation. Generate through /api/v1/production/snapshots/generate-scene with confirm=true and a stable Idempotency-Key. Poll the returned jobId. MCP uses myeq.video.preflight_scene and myeq.video.generate_scene with the same snapshot; paid submission never retries automatically. Scene settings override project defaults; preserve matching frozen sceneContracts.

Legacy /video/start, /video/create, /video/create-job and /video/preflight are retired: default/24 returns 410; 30/60 requires snapshot migration with 422. 25/48/50 are unsupported. Preflight failure never changes cadence or charges credits. A successful check does not reserve availability or wallet balance.

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 · JobGenerated ≠ Certified