> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs-dev.ltx.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs-dev.ltx.io/_mcp/server.

# Reframe a video to a new resolution

POST https://api.ltx.io/v2/video-to-video-reframe
Content-Type: application/json

Reframe a video to a new resolution. The model fills in the missing areas with generated content that matches the original. On completion, the result contains `video_url`, the source video reframed to the requested resolution.

Responds immediately with the job `id` and `created_at` timestamp. Poll `GET /v2/video-to-video-reframe/{id}` until the status is `completed`.

Billed per second of input video, by output resolution. See [Pricing](/pricing).

Reference: https://docs-dev.ltx.io/api-documentation/api-reference/async-video-generation/submit-video-to-video-reframe

## Authentication

- `Authorization` header (bearer token, required) — API key authentication

## Request

### Body (application/json)

This endpoint expects a VideoToVideoReframeRequest.

- `video_uri` (string, required) — Input video in HTTPS URL or base64 data URI format. See [Input Formats](/input-formats#video-input) for supported formats and codecs. Max 60 seconds and 1800 frames (e.g. 60s at 30fps, or 30s at 60fps).
- `resolution` (enum, required) — Target output resolution. The source video is extended to fill this frame. Pass one of the values below; each maps to an aspect ratio: | Aspect ratio | Resolutions | | --- | --- | | 1:1 (square) | `720x720`, `1080x1080` | | 4:5 (portrait) | `720x900`, `1080x1350` | | 5:4 (landscape) | `900x720`, `1350x1080` | | 9:16 (portrait) | `720x1280`, `1080x1920` | | 16:9 (landscape) | `1280x720`, `1920x1080` |
  - Allowed values: `720x720`, `1080x1080`, `720x900`, `1080x1350`, `900x720`, `1350x1080`, `720x1280`, `1080x1920`, `1280x720`, `1920x1080`
- `placement` (VideoToVideoReframeRequestPlacement, optional) — Where the source video lands on the output frame: an **Anchor** such as `{ "anchor": "top" }` to fit and align it, or a **Rectangle** such as `{ "x": 0, "y": 0.35, "width": 1 }` to set its position and size exactly (see both below). The whole source is always kept and never stretched; the model generates the rest of the frame. Omit to center it at the largest size that fits.

## Response

### 202

Job submitted successfully

- `id` (string, required) — Unique job identifier. Use this to poll for status.
- `created_at` (datetime, required) — ISO 8601 timestamp of when the job was created.

## Errors

### 400 Bad Request Error

The request is invalid or malformed

- `type` (enum, required) — Response type indicator
  - Allowed values: `error`
- `error` (ErrorError, required)

### 401 Unauthorized Error

Authentication failed

- `type` (enum, required) — Response type indicator
  - Allowed values: `error`
- `error` (ErrorError, required)

### 402 Payment Required Error

Insufficient credits

- `type` (enum, required) — Response type indicator
  - Allowed values: `error`
- `error` (ErrorError, required)

### 422 Unprocessable Entity Error

Content rejected by safety filters

- `type` (enum, required) — Response type indicator
  - Allowed values: `error`
- `error` (ErrorError, required)

### 429 Too Many Requests Error

Concurrency or queue limit exceeded

- `type` (enum, required) — Response type indicator
  - Allowed values: `error`
- `error` (ErrorError, required)

### 500 Internal Server Error

An unexpected error occurred

- `type` (enum, required) — Response type indicator
  - Allowed values: `error`
- `error` (ErrorError, required)

### 503 Service Unavailable Error

Service temporarily unavailable

- `type` (enum, required) — Response type indicator
  - Allowed values: `error`
- `error` (ErrorError, required)

## Types

### VideoToVideoReframeRequestPlacement

Where the source video lands on the output frame: an **Anchor** such as `{ "anchor": "top" }` to fit and align it, or a **Rectangle** such as `{ "x": 0, "y": 0.35, "width": 1 }` to set its position and size exactly (see both below). The whole source is always kept and never stretched; the model generates the rest of the frame. Omit to center it at the largest size that fits.

### ErrorError

- `type` (string, required) — Error type for programmatic handling
- `message` (string, required) — Human-readable error description

### Anchor

Fits the video inside the frame and aligns it, e.g. `{ "anchor": "top" }`: | `anchor` | Where the video lands | | -------------- | ------------------------------------- | | `center` | Middle (same as omitting `placement`) | | `top` | Top edge | | `bottom` | Bottom edge | | `left` | Left edge | | `right` | Right edge | | `top_left` | Top-left corner | | `top_right` | Top-right corner | | `bottom_left` | Bottom-left corner | | `bottom_right` | Bottom-right corner | The fitted video always fills the frame along one axis, so an anchor only moves it along the other: landscape source → portrait frame fills the width, so it moves up or down top center bottom ┌────┐ ┌────┐ ┌────┐ │████│ │ │ │ │ │ │ │████│ │ │ │ │ │ │ │████│ └────┘ └────┘ └────┘ portrait source → landscape frame fills the height, so it moves left or right left center right ┌──┬──────┐ ┌───┬──┬───┐ ┌──────┬──┐ │██│ │ │ │██│ │ │ │██│ │██│ │ │ │██│ │ │ │██│ └──┴──────┘ └───┴──┴───┘ └──────┴──┘ ████ = your video, the rest is generated A corner anchor such as `bottom_left` works whatever the video's orientation, and a video with the frame's aspect ratio fills it, so every anchor gives the same result. Anchors other than `center` can't enlarge the video more than 2× its original pixel size, so they may be rejected for a small video; use `center` (or omit `placement`) to fit it at any size, or use a rectangle.

- `anchor` (enum, required)
  - Allowed values: `center`, `top`, `bottom`, `left`, `right`, `top_left`, `top_right`, `bottom_left`, `bottom_right`

### Rectangle

* `x`, `y`: the video's top-left corner, as fractions of the output frame (`0, 0` is its top-left). * Send `width`, `height`, or both, as fractions of the frame. With one, the other follows the video's aspect ratio; with both, they must match it to within a pixel. * The video must stay inside the frame, be at least one pixel on each side, and can't be enlarged more than 2×. For a 1920x1080 video in a `1080x1920` frame: | `placement` | Result | | ---------------------------------------- | ------------------------------------------------------- | | `{ "x": 0, "y": 0.35, "width": 1 }` | Full width, top edge 35% down; height follows the video | | `{ "x": 0.1, "y": 0.1, "height": 0.25 }` | A quarter of the frame tall; width follows the video |

- `x` (double, required) — Left edge of the placed video, as a fraction of the output width.
- `y` (double, required) — Top edge of the placed video, as a fraction of the output height.
- `width` (double, optional) — Width of the placed video, as a fraction of the output width.
- `height` (double, optional) — Height of the placed video, as a fraction of the output height.

## Examples

### Anchor

**Request**

```json
{
  "video_uri": "YOUR_VIDEO_URI",
  "resolution": "1080x1920",
  "placement": {
    "anchor": "top"
  }
}
```

**Response**

```json
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "created_at": "2026-01-15T10:00:00.000Z"
}
```

**SDK Code**

```python Anchor
import requests

url = "https://api.ltx.io/v2/video-to-video-reframe"

payload = {
    "video_uri": "YOUR_VIDEO_URI",
    "resolution": "1080x1920",
    "placement": { "anchor": "top" }
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```go Anchor
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.ltx.io/v2/video-to-video-reframe"

	payload := strings.NewReader("{\n  \"video_uri\": \"YOUR_VIDEO_URI\",\n  \"resolution\": \"1080x1920\",\n  \"placement\": {\n    \"anchor\": \"top\"\n  }\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```java Anchor
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.ltx.io/v2/video-to-video-reframe")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"video_uri\": \"YOUR_VIDEO_URI\",\n  \"resolution\": \"1080x1920\",\n  \"placement\": {\n    \"anchor\": \"top\"\n  }\n}")
  .asString();
```

### Rectangle

**Request**

```json
{
  "video_uri": "YOUR_VIDEO_URI",
  "resolution": "1080x1920",
  "placement": {
    "x": 0,
    "y": 0.35,
    "width": 1
  }
}
```

**Response**

```json
{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "created_at": "2026-01-15T10:00:00.000Z"
}
```

**SDK Code**

```python Rectangle
import requests

url = "https://api.ltx.io/v2/video-to-video-reframe"

payload = {
    "video_uri": "YOUR_VIDEO_URI",
    "resolution": "1080x1920",
    "placement": {
        "x": 0,
        "y": 0.35,
        "width": 1
    }
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```go Rectangle
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.ltx.io/v2/video-to-video-reframe"

	payload := strings.NewReader("{\n  \"video_uri\": \"YOUR_VIDEO_URI\",\n  \"resolution\": \"1080x1920\",\n  \"placement\": {\n    \"x\": 0,\n    \"y\": 0.35,\n    \"width\": 1\n  }\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```java Rectangle
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.ltx.io/v2/video-to-video-reframe")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"video_uri\": \"YOUR_VIDEO_URI\",\n  \"resolution\": \"1080x1920\",\n  \"placement\": {\n    \"x\": 0,\n    \"y\": 0.35,\n    \"width\": 1\n  }\n}")
  .asString();
```