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

# Input Files

> Learn how to handle input files

Magic Hour's API allows you to upload various types of assets needed for video generation. This guide explains how to manage these assets effectively.

## Supported asset types

The following file extensions are supported by our APIs:

<CardGroup cols={3}>
  <Card title="Video" icon="film">
    mp4, m4v, mov, webm
  </Card>

  <Card title="Audio" icon="music">
    mp3, wav, aac, flac, webm, m4a, opus, ogg, aiff, amr
  </Card>

  <Card title="Image" icon="image">
    png, jpg, jpeg, heic, heif, webp, avif, jp2, tiff, bmp
  </Card>
</CardGroup>

<Note>`gif` extension is only supported by face swap API's `video_file_path` field.</Note>

## Available options for assets

You have two options when it comes to using input files:

* Pass a URL as the input (simplest)
* Upload to our storage (do not require hosting files yourself)

## Passing a file URL

This is the simplest method if you have the files hosted somewhere. When calling our APIs, you can simply pass the URL as the `video_file_path`, `image_file_path`, or `audio_file_path`.

For Example

```json theme={null}
{
  "assets": {
    "video_file_path": "https://svs.gsfc.nasa.gov/vis/a010000/a014300/a014327/john_bolten_no_graphics.mp4"
  }
}
```

<Tip>
  The URL can be an authenticated url, as long as we can validate the file extension is supported.
</Tip>

## Upload to Magic Hour storage

To upload assets for video generation, you'll need to follow these steps:

1. Request upload URLs for your assets, you need to specify the file extension and the type of the file.
2. Upload the files to the provided URLs by sending a PUT request.
3. Use the `file_path` value from the original upload url response in your API calls.

The following code samples provide a full example of how to upload a video file to Magic Hour storage.

<Note>
  The upload file function is only available in the following SDKs:

  * Python SDK v0.36.0 or later.
  * Node SDK v0.37.0 or later.

  We are working on adding it to the other SDKs. If you need it in an SDK that is not listed above, please [contact us](mailto:support@magichour.ai).
</Note>

<CodeGroup>
  ```python Python SDK theme={null}
  from magic_hour import Client
  import requests

  client = Client(token="YOUR_API_KEY") # change to your API key

  file_path = client.v1.files.upload_file("/path/to/your/image.jpg")

  # now you can use `file_path` in your API calls for
  # `video_file_path`, `image_file_path`, or `audio_file_path
  ```

  ```typescript Node SDK theme={null}
  import { writeFileSync } from "fs";
  import { Client } from "magic-hour";

  const client = new Client({ token: "YOUR_API_KEY" }); // change to your API key

  const filePath = await client.v1.files.uploadFile("/path/to/your/image.jpg");

  // now you can use `filePath` in your API calls for
  // `video_file_path`, `image_file_path`, or `audio_file_path`
  ```

  ```go Go SDK theme={null}
  package main

  import (
  	"fmt"
  	"net/http"
  	"os"

  	sdk "github.com/magichourhq/magic-hour-go/client"
  	"github.com/magichourhq/magic-hour-go/resources/v1/files/upload_urls"
  	"github.com/magichourhq/magic-hour-go/types"
  )

  func main() {
  	client := sdk.NewClient(sdk.WithBearerAuth(os.Getenv("API_KEY"))) // change to your API key

  	response, err := client.V1.Files.UploadUrls.Create(upload_urls.CreateRequest{
  		Items: []types.PostV1FilesUploadUrlsBodyItemsItem{
  			types.PostV1FilesUploadUrlsBodyItemsItem{ Extension: "mp4", Type: types.PostV1FilesUploadUrlsBodyItemsItemTypeEnumVideo },
  			// if you have multiple files to upload, you can request multiple upload urls
  			// the order of the response will be in the same order as the request
  			// types.PostV1FilesUploadUrlsBodyItemsItem{ Extension: "mp3", Type: types.PostV1FilesUploadUrlsBodyItemsItemTypeEnumAudio },
  			// types.PostV1FilesUploadUrlsBodyItemsItem{ Extension: "png", Type: types.PostV1FilesUploadUrlsBodyItemsItemTypeEnumImage },
  		},
  	})

  	if err != nil {
  		fmt.Println(err)
  		return
  	}

  	local_path := "/path/to/file/video.mp4" // change to your local file path
  	file, err := os.Open(local_path)
  	if err != nil {
  		fmt.Println(err)
  	}
  	defer file.Close()

  	req, err := http.NewRequest("PUT", response.Items[0].UploadUrl, file)
  	if err != nil {
  		fmt.Println(err)
  	}

  	fileClient := &http.Client{}
  	_, err = fileClient.Do(req)
  	if err != nil {
  		fmt.Println(err)
  	}

  	file_path := response.Items[0].FilePath

  	fmt.Printf("file uploaded successfully to %s\n", file_path)

  	// now you can use `file_path` in your API calls for
  	// `video_file_path`, `image_file_path`, or `audio_file_path`
  }
  ```

  ```rust Rust SDK theme={null}
  use magic_hour;

  let mut client = magic_hour::Client::default()
          .with_bearer_auth(&std::env::var("API_KEY").expect("API_KEY must be set"));

  let response = client.v1().files().upload_urls()
      .create(magic_hour::resources::v1::files::upload_urls::CreateRequest {
          items: vec![
              magic_hour::models::PostV1FilesUploadUrlsBodyItemsItem { extension: "mp4".to_string(), type_field: magic_hour::models::PostV1FilesUploadUrlsBodyItemsItemTypeEnum::Video }
              // if you have multiple files to upload, you can request multiple upload urls
              // the order of the response will be in the same order as the request
              // magic_hour::models::PostV1FilesUploadUrlsBodyItemsItem { extension: "mp3".to_string(), type_field: magic_hour::models::PostV1FilesUploadUrlsBodyItemsItemTypeEnum::Audio },
              // magic_hour::models::PostV1FilesUploadUrlsBodyItemsItem { extension: "png".to_string(), type_field: magic_hour::models::PostV1FilesUploadUrlsBodyItemsItemTypeEnum::Image },
          ],
      }).await;

  let local_path = "/path/to/file/video.mp4"; // change to your local file path
  let file = std::fs::File::open(local_path).unwrap();

  let mut req = reqwest::Client::new()
      .put(response.items[0].upload_url);

  req.body(file).send().unwrap();

  let file_path = response.items[0].file_path;

  // now you can use `file_path` in your API calls for
  // `video_file_path`, `image_file_path`, or `audio_file_path`
  ```

  ```sh cURL theme={null}
  response=$(curl https://api.magichour.ai/v1/files/upload-urls \
    --request POST \
    --header 'Content-Type: application/json' \
    --data '{
    "items": [
      { "type": "video", "extension": "mp4" }
    ]
  }')
  # if you have multiple files to upload, you can request multiple upload urls
  # the order of the response will be in the same order as the request
  # { "type": "audio", "extension": "mp3" },
  # { "type": "image", "extension": "png" },

  local_path="/path/to/file/video.mp4" # change to your local file path

  # from the result from the first curl call to upload the file
  curl $(jq -r '.items[0].upload_url' response) \
    --request PUT \
    --data-binary @${local_path}

  file_path=$(jq -r '.items[0].file_path' response)

  # now you can use `file_path` in your API calls for
  # `video_file_path`, `image_file_path`, or `audio_file_path`
  ```
</CodeGroup>

## Uploaded file lifecycle

Uploaded files are automatically cleaned up after **7 days**.

<Tip>
  You can reference the value in `.items.[].file_path` in multiple API calls before the file is
  cleaned up.
</Tip>

If you have use cases where having more permanent storage is required, please reach out to our team at [support@magichour.ai](mailto:support@magichour.ai).
