--- title: Migrate legacy Ray models | Luma Agents description: Move Ray 3, Ray 2, Ray 2 Flash, Ray 2 Relaxed, Ray 3 Reference, and Ray 3 Refiner integrations to Ray 3.2 on the Luma Agents API. --- Move legacy Luma video integrations to **Ray 3.2** on the Luma Agents API. This guide is for API customers using any of these retiring models: - Ray 3 - Ray 2 - Ray 2 Flash - Ray 2 Relaxed - Ray 3 Reference - Ray 3 Refiner If you received a deprecation notice, use the retirement date in that message as the cutoff for your account. Legacy requests will continue to work during the notice period, but begin migrating early enough to validate your production workflows before you cut over. **Use `ray-3.2` on the wire.** The public model identifier on `/v1/generations` is `ray-3.2`. Do not send an older Ray model name; legacy identifiers are not accepted by the new API. ## The migration in one view The legacy API used model variants and separate request shapes to express intent. The Luma Agents API gives you one model and a small set of composable primitives: | Decision | Legacy approach | Luma Agents API | | ------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------ | | **Where to send work** | Separate video and modify routes | `POST https://agents.lumalabs.ai/v1/generations` | | **Which model to call** | Ray 3, Ray 2, Flash, Relaxed, Reference, or Refiner | `model: "ray-3.2"` | | **What operation to run** | Implied by model or route | `type: "video"`, `"video_edit"`, or `"video_reframe"` | | **What media to use** | Route-specific `media` and `keyframes` shapes | `source`, `video.start_frame`, `video.end_frame`, or `video.*.keyframes` | | **How to tune output** | Top-level fields and model variants | Common settings under `video`; edit settings under `video.edit` | | **How to get the result** | Async generation object | Submit once, poll `GET /v1/generations/{id}`, download `output[].url` | ### Choose the primitive that matches your job | What you want to do | `type` | Core inputs | Start here | | ---------------------------------------- | --------------- | --------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | | Generate from text | `video` | `prompt` | [Text-to-video](/guides/videos/generation#basic-request--text-to-video/index.md) | | Animate one image | `video` | `video.start_frame` | [Image-to-video](/guides/videos/generation#image-to-video-with-anchor-frames/index.md) | | Interpolate between two images | `video` | `video.start_frame` + `video.end_frame` | [Image-to-video](/guides/videos/generation#image-to-video-with-anchor-frames/index.md) | | Direct a new clip with several images | `video` | `video.keyframes` + `video.keyframe_indexes` | [Multi-keyframe generation](/guides/videos/generation#multi-keyframe-image-to-video/index.md) | | Continue a completed Luma video | `video` | One `generation_id` in `video.start_frame` or `video.end_frame` | [Extend a video](/guides/videos/generation#extending-a-prior-video/index.md) | | Restyle, refine, or transform a video | `video_edit` | `source` + optional `video.edit` | [Video editing](/guides/videos/editing/index.md) | | Pin the look of an edit at exact moments | `video_edit` | `source` + `video.edit.keyframes` + indexes | [Edit keyframes](/guides/videos/editing#keyframes--the-control-surface-for-edits/index.md) | | Change a video’s aspect ratio | `video_reframe` | `source` + target `aspect_ratio` | [Video reframing](/guides/videos/reframing/index.md) | ## After your new account is provisioned 1. **Create an API key** in the [Luma developer dashboard](https://platform.lumalabs.ai). New keys begin with `luma-api-` and are shown only once. 2. **Store the key on your server** as `LUMA_AGENTS_API_KEY`. Do not expose it in browser or mobile code. 3. **Point your client to** `https://agents.lumalabs.ai/v1`. 4. **Confirm `ray-3.2` access** with the [Playground](https://platform.lumalabs.ai/playground), then copy its generated cURL for your first request shape. 5. **Port one workflow at a time** using the primitive matrix above. Terminal window ``` export LUMA_AGENTS_API_KEY="luma-api-..." curl -X POST https://agents.lumalabs.ai/v1/generations \ -H "Authorization: Bearer $LUMA_AGENTS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "ray-3.2", "type": "video", "prompt": "A slow dolly through a greenhouse at sunrise", "aspect_ratio": "16:9", "video": { "resolution": "720p", "duration": "5s" } }' ``` The response is a generation object in `queued` state. Save its `id`; you use that same id to poll, edit, extend, or reframe the result. ## Map each retiring model by intent Do not look for one new model name per retired model. Every row below uses `model: "ray-3.2"`; the request’s `type`, media references, and controls now express the difference. | Retiring model or workflow | New request shape | What changed | | -------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | | **Ray 3** | `type: "video"` | Use the standard generation primitive for text-to-video and image-to-video. | | **Ray 2** | `type: "video"` | Move output controls under `video` and re-evaluate prompts and output quality. | | **Ray 2 Flash** | `type: "video"` | There is no separate Flash model identifier. Benchmark Ray 3.2 latency and adjust timeouts and concurrency for your account. | | **Ray 2 Relaxed** | `type: "video"` | There is no separate Relaxed model identifier. Preserve your creative intent in the prompt and anchor frames. | | **Ray 3 Reference** | `type: "video"` or `"video_edit"` with keyframes | Use generation keyframes to direct a new clip, or edit keyframes to direct changes to an existing clip. | | **Ray 3 Refiner** | `type: "video_edit"` with `source` | Start with `video.edit.auto_controls: true`; add `strength`, per-signal controls, or keyframes only when you need more control. | The quickest migration path is to preserve the **job’s intent**, not the old model selection. First choose `video`, `video_edit`, or `video_reframe`; then add only the media references and controls that operation needs. ## Translate the request envelope | Legacy field or behavior | New field or behavior | Migration note | | ----------------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | | `POST .../generations/video` | `POST /v1/generations` + `type: "video"` | Text-to-video, image-to-video, interpolation, and extend share one type. | | `POST .../generations/video/modify` | `POST /v1/generations` + `type: "video_edit"` | The route no longer selects the operation. | | Any retiring model identifier | `model: "ray-3.2"` | Use this exact public wire value. | | Dedicated HDR model | `video.hdr: true` | HDR is a control, not a model. See [video generation constraints](/guides/videos/generation#validation-rules/index.md). | | Top-level `resolution`, `duration`, `loop` | `video.resolution`, `video.duration`, `video.loop` | Common video settings now live together. | | `keyframes.frame0` | `video.start_frame` | Drop the old `type` discriminator. | | `keyframes.frame1` | `video.end_frame` | Set both start and end images to interpolate. | | Generation keyframe `{ "type": "generation", "id": "..." }` | `{ "generation_id": "..." }` | A single generation ref in `start_frame` extends forward; one in `end_frame` extends backward. | | Modify `media.url` | `source: { "url": "...", "media_type": "video/mp4" }` | Or use `source.generation_id` / `source.file_id`. | | Modify `mode` | `video.edit.strength` | Values are `adhere_1`–`3`, `flex_1`–`3`, and `reimagine_1`–`3`. | | `callback_url` | Poll `GET /v1/generations/{id}` | The Agents API result flow is submit, poll, download. | ### Before and after: generate a video ``` // Legacy { "model": "ray-3", "prompt": "A fox runs through fresh snow", "resolution": "720p", "duration": "5s", "aspect_ratio": "16:9" } // Luma Agents API { "model": "ray-3.2", "type": "video", "prompt": "A fox runs through fresh snow", "aspect_ratio": "16:9", "video": { "resolution": "720p", "duration": "5s" } } ``` ### Before and after: refine an existing video ``` // Legacy modify/refiner request { "model": "ray-3", "prompt": "Transform the scene into moonlit 35mm film footage", "media": { "url": "https://example.com/source.mp4" }, "mode": "flex_2" } // Luma Agents API { "model": "ray-3.2", "type": "video_edit", "prompt": "Transform the scene into moonlit 35mm film footage", "source": { "url": "https://example.com/source.mp4", "media_type": "video/mp4" }, "video": { "edit": { "auto_controls": true } } } ``` Start edits in automatic mode. If you need predictable source adherence, replace `auto_controls` with a [`strength` preset](/guides/videos/editing#strength/index.md). For precise creative direction, add [keyframes at specific source-frame indexes](/guides/videos/editing#keyframes--the-control-surface-for-edits/index.md). ## Understand the new media primitives The same reference shapes are reused across generation, editing, and reframing. Choose the form that best matches where the media already lives: | Reference | Use when | Shape | | ----------------- | ----------------------------------------------------------------- | ---------------------------------------------------------------------- | | Hosted media | The asset is available at a public URL | `{ "url": "https://...", "media_type": "video/mp4" }` for source video | | Uploaded file | You want to upload once and reuse the asset | `{ "file_id": "..." }` from the [Files API](/guides/files/index.md) | | Inline data | The asset is small and cannot be hosted | `{ "data": "", "media_type": "video/mp4" }` | | Prior Luma result | The asset came from a completed generation on the same API client | `{ "generation_id": "..." }` | Not every reference form is valid in every position. The linked generation, editing, and reframing guides list the exact combinations. As a rule of thumb, use `source` for the video being changed and keyframe fields for images that direct the result. ## Poll and download `POST /v1/generations` returns immediately. Poll the returned id until `state` is `completed` or `failed`: Terminal window ``` GENERATION_ID="" curl -H "Authorization: Bearer $LUMA_AGENTS_API_KEY" \ "https://agents.lumalabs.ai/v1/generations/$GENERATION_ID" ``` | State | Meaning | What your integration should do | | ------------ | --------------------------------- | ------------------------------------------------------------------------------------------------- | | `queued` | Accepted and waiting for capacity | Continue polling with backoff. | | `processing` | Generation is running | Continue polling. | | `completed` | Output is ready | Download each `output[].url`. | | `failed` | The job did not complete | Log `failure_code`, `failure_reason`, and `X-Request-Id`; retry only when the error is transient. | Output URLs expire after one hour. Poll the generation again to mint a fresh URL if needed. ## Cut over safely Use this checklist for each production workflow: - [ ] Inventory every call using a retiring model, including background jobs and rarely used fallback paths. - [ ] Group calls by intent: generate, edit/refine, extend, or reframe. - [ ] Port each group to its new `type` and request shape. - [ ] Run representative prompts and media through the [Playground](https://platform.lumalabs.ai/playground). - [ ] Compare output quality, latency, failure handling, and cost with your current production baseline. - [ ] Update polling deadlines and concurrency handling; do not carry Ray 2 Flash timing assumptions forward. - [ ] Confirm your integration records generation `id`, `state`, `failure_code`, and `X-Request-Id`. - [ ] Route a small percentage of production traffic to the new API, then ramp up while watching errors and latency. - [ ] Move all traffic before the retirement date in your deprecation notice, then remove legacy model identifiers and fallback code. ## Common migration mistakes | Symptom | Likely cause | Fix | | ----------------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------- | | `Unknown model` | Sent a retired model identifier | Send `model: "ray-3.2"`. | | Type is not supported for model | Reused an image type or omitted the video operation | Use `video`, `video_edit`, or `video_reframe` from the primitive matrix. | | Video options have no effect or fail validation | Left output fields at the top level | Move them under `video`. | | Source URL is rejected | Omitted its MIME type | Add `source.media_type`, such as `video/mp4`. | | Edit source is rejected for duration | Source is longer than 18 seconds | Trim it to 18 seconds or shorter. Reframe sources must be 10 seconds or shorter. | | A completed generation cannot be referenced | It belongs to another API client or is not complete | Use a completed generation owned by the same client, or pass a URL / uploaded file instead. | | Client waits forever | Polling recognizes only the old lifecycle values | Stop on `completed` or `failed` and enforce a deadline. | ## Need migration help? If you need help planning your cutover or meeting the timing in your deprecation notice, email . For request-shape or runtime issues, include: - the retiring model or workflow you are replacing; - a redacted old request and new request; - the new generation id and `X-Request-Id`; - the HTTP status, `failure_code`, and `failure_reason`. ## Continue with the full references - [Video generation](/guides/videos/generation/index.md) — text, image, multi-keyframe, extend, loop, and HDR - [Video editing](/guides/videos/editing/index.md) — source media, automatic controls, strength, advanced controls, and keyframes - [Video reframing](/guides/videos/reframing/index.md) — target aspect ratios and source placement - [Files API](/guides/files/index.md) — upload media once and reference it by `file_id` - [Error handling](/guides/error-handling/index.md) — HTTP errors, generation failures, and retry guidance - [Pricing](/guides/pricing/index.md) — current Ray 3.2 rates and Provisioned Throughput