Skip to main content
Beta — this feature is rolling out gradually. A team outside the beta gets 403 with the code DITTO_BETA_REQUIRED from every Ditto endpoint, and can join the waitlist from Ditto in the app.
Ditto replaces characters, props and backgrounds in an existing video using reference images. One request can carry up to 30 replacements, and they are all applied together in a single generation with one price and one output video. Every Ditto endpoint lives under /api/v1/ditto:

1. Upload the video and reference images

Upload the source video (MP4 or MOV) and each reference image with the endpoints under Uploads in the API reference: POST /upload/init, POST /upload/sign-part and POST /upload/complete. Keep the assetId each upload returns. You can also reuse the asset IDs of files already in your team.

Use an avatar instead of uploading an image

To cast one of your team’s avatars or a Melius avatar, list them with GET /ditto/avatars:
custom avatars are your team’s own. curated avatars are made by Melius. Send an avatar’s kind and id as a replacement’s avatar, in place of its referenceAssetId:
An avatar your team can’t use answers 404, and one whose image isn’t made yet answers 409.

2. Start the video

Send the source video and an ordered replacements list. Each item has a referenceAssetId or an avatar, a targetKind (character, prop or background) and an optional targetDescription naming what it replaces in the video. Starting a video needs an editor role on the team and charges its price to the team.
A targetDescription is optional for characters: Ditto picks the main person, or distinct people in reference order when there are several. It is required when two or more items replace props, or two or more replace backgrounds. Optional fields:
  • maxCredits — the most credits the video may cost. A higher price answers 402 and starts nothing.
  • sourceRange — { "startMs": 0, "endMs": 5000 } to use part of the video. The full video is used otherwise.
  • modelId and resolution — leave them out to use Ditto’s default. GET /ditto/models lists both.
  • audioMode — original (default) keeps the video’s audio; mute removes it.
  • additionalInstructions — extra direction that applies to every replacement. With it, replacements can be left out.
The response is 202 with a generationId and status: "preparing". When no model can make the video, the response is 400 and its message lists the reasons, such as a source longer than the model takes.

Retry safely

Save an Idempotency-Key before sending the request. If you lose the response, resend the identical request with the same key, and you get the original response back instead of a second video. Resending without a key starts another paid video. See Retry a submission safely for the conflict responses.

3. Get the result

Poll GET /ditto/<generationId> until status is ready or failed. preparing, rendering and finalizing mean it is still working, and estimatedWait gives the typical wait in seconds for its model. When it is ready, videoUrl links to the finished video and outputAssetId is its asset in your team. A failed video includes a failureMessage.
Last modified on November 11, 2026