> ## Documentation Index
> Fetch the complete documentation index at: https://docs.topyappers.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Remix API Overview

> Process videos and images with the TopYappers Remix API

<Note>
  **Remove Invisible Watermarks from AI-Generated Media**

  The Remix API helps you remove invisible watermarks that AI media generation platforms add to their content. Process videos or images through our API to get clean output for your use cases.
</Note>

## Introduction

The Remix API allows you to process video and image files by providing public media URLs. The API downloads the media from the provided URL, applies your specified transformations, and processes it to remove invisible watermarks.

<Note>
  **Upload Your Media First**

  Before using the Remix API, upload your video or image file to cloud storage such as **Cloudflare R2** or **AWS S3** and make it publicly accessible. The API requires direct URLs to your media files.
</Note>

## Authentication

All requests to the Remix API require authentication using an API key passed in the `x-ty-api-key` header.

```bash theme={null}
x-ty-api-key: your-api-key-here
```

## Endpoints

```bash Video theme={null}
POST https://www.topyappers.com/api/v1/remix
```

```bash Images theme={null}
POST https://www.topyappers.com/api/v1/image-rewrite
```

## How to Upload Your Media

Before using the Remix API, you need to upload your media to cloud storage. Here are the recommended options:

### Option 1: Cloudflare R2 Storage

Cloudflare R2 offers S3-compatible storage with no egress fees.

1. Create an R2 bucket in your Cloudflare dashboard
2. Upload your video or image file to the bucket
3. Make the bucket or object publicly accessible
4. Use the public URL in your API request

**Example R2 URLs**: `https://pub-abc123.r2.dev/my-video.mp4`, `https://pub-abc123.r2.dev/image-1.jpg`

### Option 2: AWS S3 Storage

AWS S3 is a widely-used object storage service.

1. Create an S3 bucket in your AWS console
2. Upload your video or image file to the bucket
3. Configure the bucket policy or object ACL to allow public read access
4. Use the public URL in your API request

**Example S3 URLs**: `https://my-bucket.s3.amazonaws.com/my-video.mp4`, `https://my-bucket.s3.amazonaws.com/image-1.jpg`

### Other Storage Options

Any cloud storage service that provides publicly accessible URLs will work, including:

* Google Cloud Storage
* Azure Blob Storage
* DigitalOcean Spaces
* Backblaze B2

<Warning>
  **Security Note**: Only make media publicly accessible that you're comfortable
  sharing. Consider using signed URLs with expiration times for sensitive
  content.
</Warning>

## Request Format

### Video Request

`POST /api/v1/remix` accepts JSON with the following fields:

| Field        | Type   | Required | Description                                         |
| ------------ | ------ | -------- | --------------------------------------------------- |
| `video_url`  | String | Yes      | URL to the video file (must be publicly accessible) |
| `parameters` | Object | No       | Optional processing parameters                      |

### Video Processing Parameters

The `parameters` field accepts an object with optional processing parameters. All parameters are optional and will use default values if not specified.

| Parameter              | Type    | Default       | Range/Values               | Description                                  |
| ---------------------- | ------- | ------------- | -------------------------- | -------------------------------------------- |
| `zoomFactor`           | number  | 1.0           | 0.1 - 5.0                  | Zoom level for the video                     |
| `hue`                  | number  | 0.0           | -180 to 180                | Hue adjustment in degrees                    |
| `playbackSpeed`        | number  | 1.0           | 0.1 - 5.0                  | Video playback speed multiplier              |
| `saturation`           | number  | 1.0           | 0.0 - 3.0                  | Color saturation multiplier                  |
| `brightness`           | number  | 0.0           | -1.0 to 1.0                | Brightness adjustment                        |
| `contrast`             | number  | 1.0           | 0.0 - 3.0                  | Contrast multiplier                          |
| `volume`               | number  | 1.0           | 0.0 - 2.0                  | Audio volume multiplier                      |
| `removeAudio`          | boolean | false         | true/false                 | Whether to remove audio from the video       |
| `algorithmFingerprint` | string  | "Fingerprint" | Any string                 | Algorithm identifier for processing          |
| `deviceMedia`          | string  | -             | See supported values below | Target device profile for media optimization |
| `hueShift`             | number  | 0.0           | -180 to 180                | Additional hue shift in degrees              |
| `gamma`                | number  | 1.0           | 0.1 - 3.0                  | Gamma correction value                       |
| `temperature`          | number  | 1.0           | 0.5 - 2.0                  | Color temperature adjustment                 |
| `noise`                | number  | 0.0           | 0.0 - 1.0                  | Amount of noise to add                       |
| `sharpness`            | number  | 1.0           | 0.0 - 3.0                  | Sharpness multiplier                         |
| `blend`                | number  | 0.0           | 0.0 - 1.0                  | Blending amount                              |
| `bilateVariation`      | number  | 1.0           | 0.0 - 2.0                  | Bilateral filter variation                   |
| `frameBlending`        | number  | 0.0           | 0.0 - 1.0                  | Amount of frame blending                     |
| `timeShift`            | number  | 0.0           | -10.0 to 10.0              | Time shift in seconds                        |

#### Supported `deviceMedia` Values

```typescript theme={null}
export enum DeviceModel {
  IPHONE_17_PRO_MAX = "iPhone 17 Pro Max",
  IPHONE_17_PRO = "iPhone 17 Pro",
  IPHONE_17 = "iPhone 17",
  IPHONE_16_PRO_MAX = "iPhone 16 Pro Max",
  IPHONE_16_PRO = "iPhone 16 Pro",
  IPHONE_16 = "iPhone 16",
  IPHONE_15_PRO_MAX = "iPhone 15 Pro Max",
  IPHONE_15_PRO = "iPhone 15 Pro",
  IPHONE_15 = "iPhone 15",
  IPHONE_14_PRO_MAX = "iPhone 14 Pro Max",
  IPHONE_14_PRO = "iPhone 14 Pro",
  IPHONE_14 = "iPhone 14",
  IPHONE_13_PRO_MAX = "iPhone 13 Pro Max",
  IPHONE_13_PRO = "iPhone 13 Pro",
  IPHONE_13 = "iPhone 13",
  META_RAYBAN = "Ray-Ban Meta Smart Glasses",
}
```

#### Example with Multiple Parameters

```json theme={null}
{
  "video_url": "https://pub-abc123.r2.dev/my-video.mp4",
  "parameters": {
    "playbackSpeed": 1.2,
    "brightness": 0.1,
    "contrast": 1.1,
    "saturation": 1.2,
    "hue": 15,
    "zoomFactor": 1.05,
    "removeAudio": false,
    "deviceMedia": "iPhone 16 Pro"
  }
}
```

### Image Request

`POST /api/v1/image-rewrite` accepts either a single `image_url` or an `images` array for batch processing.

| Field        | Type   | Required                            | Description                                                                    |
| ------------ | ------ | ----------------------------------- | ------------------------------------------------------------------------------ |
| `image_url`  | String | Yes, unless `images` is provided    | URL to a single image file                                                     |
| `images`     | Array  | Yes, unless `image_url` is provided | Up to 20 image objects with `image_url` and optional image-specific parameters |
| `parameters` | Object | No                                  | Optional global image processing parameters applied to every image             |

#### Image Processing Parameters

| Parameter        | Type    | Default | Range/Values               | Description                            |
| ---------------- | ------- | ------- | -------------------------- | -------------------------------------- |
| `zoomFactor`     | number  | 1.0     | 0.5 - 2.0                  | Zoom level for the image               |
| `saturation`     | number  | 1.0     | 0.0 - 2.0                  | Color saturation multiplier            |
| `brightness`     | number  | 0.0     | -1.0 to 1.0                | Brightness adjustment                  |
| `contrast`       | number  | 1.0     | 0.0 - 2.0                  | Contrast multiplier                    |
| `hue`            | number  | 0.0     | -180 to 180                | Hue adjustment in degrees              |
| `hueShift`       | number  | 0.0     | -180 to 180                | Alias for hue adjustment               |
| `gamma`          | number  | 1.0     | 0.1 - 3.0                  | Gamma correction value                 |
| `temperature`    | number  | 1.0     | 0.1 - 2.0                  | Color temperature adjustment           |
| `noise`          | number  | 0.0     | 0.0 - 0.5                  | Amount of noise to add                 |
| `sharpness`      | number  | 1.0     | 0.0 - 2.0                  | Sharpness multiplier                   |
| `quality`        | integer | 94      | 60 - 100                   | Output image quality                   |
| `flipHorizontal` | boolean | false   | true/false                 | Whether to flip the image horizontally |
| `flipVertical`   | boolean | false   | true/false                 | Whether to flip the image vertically   |
| `deviceModel`    | string  | -       | See supported values above | Target device profile for metadata     |

#### Image Batch Example

```json theme={null}
{
  "images": [
    {
      "image_url": "https://pub-abc123.r2.dev/image-1.jpg"
    },
    {
      "image_url": "https://pub-abc123.r2.dev/image-2.jpg",
      "brightness": 0.03
    }
  ],
  "parameters": {
    "brightness": 0.02,
    "contrast": 1.05,
    "quality": 94,
    "deviceModel": "iPhone 16 Pro"
  }
}
```

## Response Format

### Success Response (200 OK)

#### Video

```json theme={null}
{
  "data": {
    "inputVideoUrl": "https://storage.topyappers.com/uploads/abc123.mp4",
    "result": "Video processing initiated"
  }
}
```

#### Images

```json theme={null}
{
  "success": true,
  "message": "Images processed successfully",
  "data": {
    "imageCount": 2,
    "inputImageUrls": [
      "https://pub-abc123.r2.dev/image-1.jpg",
      "https://pub-abc123.r2.dev/image-2.jpg"
    ],
    "processedImages": [
      {
        "url": "https://imgrework.topyappers.com/processed-image-1.jpg",
        "applied_params": {
          "brightness": 0.02,
          "contrast": 1.05,
          "quality": 94
        }
      }
    ],
    "processingTime": 8.42
  }
}
```

### Error Responses

* **400 Bad Request**: Invalid media URL or parameters
* **401 Unauthorized**: Invalid or missing API key
* **413 Payload Too Large**: Video file exceeds size limit
* **429 Too Many Requests**: Rate limit exceeded

## Code Examples

<CodeGroup>
  ```python Python theme={null}
  import requests
  import json

  API_KEY = "your-api-key-here"
  BASE_URL = "https://www.topyappers.com"
  # Video URL from Cloudflare R2 or AWS S3
  VIDEO_URL = "https://pub-abc123.r2.dev/my-video.mp4"

  # Optional parameters for video processing
  parameters = {
      "playbackSpeed": 1.2,
      "brightness": 0.1,
      "contrast": 1.1,
      "saturation": 1.2,
      "hue": 15,
      "zoomFactor": 1.05,
      "deviceMedia": "iPhone 16 Pro"
  }

  def process_video():
      url = f"{BASE_URL}/api/v1/remix"

      headers = {
          "x-ty-api-key": API_KEY,
          "Content-Type": "application/json"
      }

      payload = {
          "video_url": VIDEO_URL,
          "parameters": parameters
      }

      print(f"Processing {VIDEO_URL}...")
      response = requests.post(url, headers=headers, json=payload)

      if response.status_code == 200:
          result = response.json()
          print("✅ Success!")
          print(f"Input URL: {result['data']['inputVideoUrl']}")
          if 'result' in result['data']:
              print(f"Result: {result['data']['result']}")
          return result
      else:
          print(f"❌ Error {response.status_code}: {response.text}")
          return None

  if __name__ == "__main__":
      result = process_video()
      if result:
          print(f"\nFull response:\n{json.dumps(result, indent=2)}")
  ```

  ```javascript JavaScript theme={null}
  const fetch = require("node-fetch");

  const API_KEY = "your-api-key-here";
  const BASE_URL = "https://www.topyappers.com";
  // Video URL from Cloudflare R2 or AWS S3
  const VIDEO_URL = "https://my-bucket.s3.amazonaws.com/my-video.mp4";

  // Optional parameters for video processing
  const parameters = {
    playbackSpeed: 1.2,
    brightness: 0.1,
    contrast: 1.1,
    saturation: 1.2,
    hue: 15,
    zoomFactor: 1.05,
    deviceMedia: "iPhone 16 Pro",
  };

  async function processVideo() {
    const url = `${BASE_URL}/api/v1/remix`;

    const payload = {
      video_url: VIDEO_URL,
      parameters: parameters,
    };

    try {
      const response = await fetch(url, {
        method: "POST",
        headers: {
          "x-ty-api-key": API_KEY,
          "Content-Type": "application/json",
        },
        body: JSON.stringify(payload),
      });

      const result = await response.json();

      if (response.ok) {
        console.log("✅ Success!");
        console.log(`Input URL: ${result.data.inputVideoUrl}`);
        if (result.data.result) {
          console.log(`Result: ${result.data.result}`);
        }
        return result;
      } else {
        console.error(`❌ Error ${response.status}: ${JSON.stringify(result)}`);
        return null;
      }
    } catch (error) {
      console.error(`❌ Error: ${error.message}`);
      return null;
    }
  }

  processVideo();
  ```

  ```typescript TypeScript theme={null}
  async function processVideo(
    videoUrl: string,
    parameters: object,
    apiKey: string,
  ): Promise<any> {
    const baseUrl = "https://www.topyappers.com";

    const response = await fetch(`${baseUrl}/api/v1/remix`, {
      method: "POST",
      headers: {
        "x-ty-api-key": apiKey,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        video_url: videoUrl,
        parameters: parameters,
      }),
    });

    if (!response.ok) {
      throw new Error(`API error: ${response.status}`);
    }

    return await response.json();
  }

  // Usage with R2 URL
  const result = await processVideo(
    "https://pub-abc123.r2.dev/video.mp4",
    { playbackSpeed: 1.2, brightness: 0.1, deviceMedia: "iPhone 16 Pro" },
    "YOUR_API_KEY",
  );

  console.log("🎉 Processing complete:", result);
  ```

  ```bash cURL theme={null}
  curl -X POST https://www.topyappers.com/api/v1/remix \
    -H "x-ty-api-key: your-api-key-here" \
    -H "Content-Type: application/json" \
    -d '{
      "video_url": "https://pub-abc123.r2.dev/video.mp4",
      "parameters": {
        "playbackSpeed": 1.2,
        "brightness": 0.1,
        "contrast": 1.1,
        "saturation": 1.2,
        "hue": 15,
        "zoomFactor": 1.05,
        "deviceMedia": "iPhone 16 Pro"
      }
    }'
  ```
</CodeGroup>

## React Example (Complete Component)

```tsx theme={null}
import { useState } from "react";

export function VideoRemixProcessor() {
  const [videoUrl, setVideoUrl] = useState("");
  const [result, setResult] = useState<any>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!videoUrl) return;

    setLoading(true);
    setError("");
    setResult(null);

    try {
      const response = await fetch("https://www.topyappers.com/api/v1/remix", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "x-ty-api-key": process.env.NEXT_PUBLIC_API_KEY!,
        },
        body: JSON.stringify({
          video_url: videoUrl,
          parameters: {
            playbackSpeed: 1.2,
            brightness: 0.1,
            contrast: 1.1,
            deviceMedia: "iPhone 16 Pro",
          },
        }),
      });

      if (!response.ok) {
        throw new Error(`API error: ${response.status}`);
      }

      const data = await response.json();
      setResult(data);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="url"
        placeholder="https://pub-abc123.r2.dev/video.mp4"
        value={videoUrl}
        onChange={(e) => setVideoUrl(e.target.value)}
        required
      />
      <p className="hint">Enter URL from Cloudflare R2 or AWS S3</p>

      <button type="submit" disabled={!videoUrl || loading}>
        {loading ? "Processing..." : "Process Video"}
      </button>

      {error && (
        <div className="error">
          <p>❌ Error: {error}</p>
        </div>
      )}

      {result && (
        <div className="result">
          <h3>✅ Complete!</h3>
          <pre>{JSON.stringify(result, null, 2)}</pre>
        </div>
      )}
    </form>
  );
}
```

## Media URL Requirements

Your media must be uploaded to cloud storage (Cloudflare R2, AWS S3, etc.) before processing. The URL must meet these requirements:

* **Publicly Accessible**: The media URL must be publicly accessible (no authentication required)
* **Cloud Storage**: Must be hosted on Cloudflare R2, AWS S3, or similar cloud storage
* **Direct Links**: URL must point directly to the media file (not a webpage)
* **Video Formats**: MP4, MOV, AVI, WebM
* **Video Max File Size**: 150MB
* **Image Formats**: JPG, PNG, WebP, GIF
* **Image Batch Size**: Maximum 20 images per request

## Error Handling

### 400 Bad Request

```json theme={null}
{
  "error": "Invalid media URL or parameters"
}
```

### 401 Unauthorized

```json theme={null}
{
  "error": "Invalid API key"
}
```

### 429 Too Many Requests

```json theme={null}
{
  "error": "Daily limit exceeded. Upgrade your plan or try in 24 hours.",
  "retryAfter": 86400,
  "limit": 100
}
```

### 413 File Too Large

```json theme={null}
{
  "error": "Video file too large. Maximum size is 150MB"
}
```

## Retry Logic Example

```typescript theme={null}
async function processVideoWithRetry(
  videoUrl: string,
  parameters: object,
  apiKey: string,
  maxRetries = 3,
) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await processVideo(videoUrl, parameters, apiKey);
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
      await new Promise((resolve) => setTimeout(resolve, delay));
    }
  }
}
```

## Best Practices

1. **Valid URLs**: Ensure media URLs are publicly accessible and point directly to media files
2. **File Size**: Keep video files under 150MB and image batches at 20 images or fewer
3. **File Formats**: Use supported formats for the media type you are processing
4. **Error Handling**: Always implement proper error handling for network and API errors
5. **Rate Limits**: Be mindful of rate limits and implement retry logic with exponential backoff
6. **API Keys**: Keep your API keys secure and never commit them to version control

## Rate Limits

Please refer to the [Rate Limits](/rate-limits) documentation for information about API rate limits and best practices.
