API changelog

What changed in the public API, newest first.

Compatibility promise#

This API is versioned by path. Additions that do not break an existing integration — a new operation, a new optional field, a new error code — are announced here and shipped on /v1. Anything incompatible ships as /v2: /v1 never changes meaning under you, and never disappears without notice.

Several voices in one video#

Version: 1.1.02026-10-21

  • POST /v1/uploads/{id}/speakers asks for the speaker detection of a pre-flighted upload, and GET /v1/uploads/{id}/speakers reads it: its status and, once ready, each speaker with the stretches in which it talks and a short clip of its own voice. The detection consumes no minutes.
  • POST /v1/jobs accepts an optional speakers list: per variant, another voice for some speakers of the video, for the minutes of one voice. Without it, a conversion is exactly what it was.
  • JobVariant gains speakers: the speakers of the variant converted with another voice, empty when the whole video takes the variant voice.
  • Four error codes: speakers_mismatch (400), multi_voice_disabled (403), speakers_not_ready (409) and upload_expired (409), the last one reserved for the resumable upload, which /v1 does not offer yet.
  • The MCP tools keep converting with one voice per variant (several voices is REST-only for now); the job they return carries the read-only speakers of each variant like any other.

Documentation release#

Version: 1.0.12026-10-01

  • The OpenAPI 3.1 document is served at GET /openapi.json, beside /v1 and without a credential, so a typed client can be generated from the contract the API actually runs.
  • The quick start now carries the Content-Type header on the PUT of the upload, as the contract requires: it is the media type the stored file keeps and the download answers with, and curl --upload-file sends none on its own. No operation changed.
  • Complete Node.js and Python programs of the whole flow (upload, pre-flight, conversion, polling, download), ready-to-paste configuration for Claude, Claude Code and Cursor, the live rate limits and daily overage cap, the job lifecycle and the options a key carries, all on the documentation page.

First public version#

Version: 1.0.02026-09-15

  • 11 REST operations over voices, uploads, conversions, narrations and downloads — the same use cases as the web app, the same minutes and the same billing.
  • An API key (x-api-key, or Authorization: Bearer miy_…) created in Settings → API authenticates /v1. MCP clients authenticate with an OAuth 2.1 access token instead, and that token opens /api/mcp and nothing else: it never authenticates /v1.
  • 5 scopes, closed: voices:read, jobs:read, jobs:write, narrations:write, webhooks:manage (webhooks:manage is reserved: no v1 operation requires it yet).
  • One error envelope, { error: { code, message, requestId } }, with a closed catalogue of codes published as x-error-catalog. error.message follows Accept-Language; codes and field names never do.
  • Cursor pagination on every list, an Idempotency-Key on every operation that consumes minutes, and a per-credential daily overage cap.
  • 2 signed outbound webhook events (job.completed, job.failed), verified with the MIY-Signature header.
  • A remote MCP server with 8 tools over the same contract, authorised with OAuth 2.1 and dynamic client registration.
  • The full reference, the quick start and this changelog are generated from openapi.json, so the documentation cannot drift from the API.