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

# Generate Signed URL for File Upload

> Generate a pre-signed URL for secure file upload to storage. This endpoint provides a temporary URL that allows direct upload of media files without exposing credentials.

## Overview

Generate a pre-signed URL that enables secure, direct upload of media files to storage without exposing your credentials. The signed URL is temporary and automatically expires after 24 hours.

<Note>
  You need a valid API key to use this endpoint. Get your API key from the [API Access page](https://app.pictory.ai/api-access) in your Pictory dashboard.
</Note>

***

## How to Generate a Signed URL and Upload a File

### Step 1: Generate a Signed URL

Request a signed URL from the API to obtain temporary upload credentials.

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.pictory.ai/pictoryapis/v1/media/generateurl \
    --header 'Authorization: YOUR_API_KEY' \
    --header 'Content-Type: application/json' \
    --data '{
      "fileName": "sample1.mp3",
      "contentType": "audio/mpeg"
    }' | python -m json.tool
  ```

  ```python Python theme={null}
  import requests

  url = "https://api.pictory.ai/pictoryapis/v1/media/generateurl"
  headers = {
      "Authorization": "YOUR_API_KEY",
      "Content-Type": "application/json"
  }
  payload = {
      "fileName": "sample1.mp3",
      "contentType": "audio/mpeg"
  }

  response = requests.post(url, json=payload, headers=headers)
  data = response.json()
  signed_url = data["data"]["signedUrl"]
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.pictory.ai/pictoryapis/v1/media/generateurl', {
    method: 'POST',
    headers: {
      'Authorization': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      fileName: 'sample1.mp3',
      contentType: 'audio/mpeg'
    })
  });

  const data = await response.json();
  const signedUrl = data.data.signedUrl;
  ```
</CodeGroup>

### Step 2: Upload Your File

Use the signed URL to upload your file directly to storage via a PUT request.

<CodeGroup>
  ```bash cURL theme={null}
  curl --location --request PUT 'SIGNED_URL_FROM_STEP_1' \
    --header 'Content-Type: audio/mpeg' \
    --data-binary '@/path/to/your/sample1.mp3'
  ```

  ```python Python theme={null}
  import requests

  with open('/path/to/your/sample1.mp3', 'rb') as file:
      response = requests.put(
          signed_url,
          data=file,
          headers={'Content-Type': 'audio/mpeg'}
      )

  if response.status_code == 200:
      print("File uploaded successfully!")
  ```

  ```javascript JavaScript theme={null}
  const fileInput = document.querySelector('input[type="file"]');
  const file = fileInput.files[0];

  const uploadResponse = await fetch(signedUrl, {
    method: 'PUT',
    headers: {
      'Content-Type': 'audio/mpeg'
    },
    body: file
  });

  if (uploadResponse.ok) {
    console.log('File uploaded successfully!');
  }
  ```
</CodeGroup>

## Request

### Headers

<ParamField header="Authorization" type="string" required>
  API key for authentication (starts with `pictai_`)

  ```
  Authorization: YOUR_API_KEY
  ```
</ParamField>

### Body Parameters

<ParamField body="fileName" type="string" required>
  Name of the file to be uploaded (e.g., `sample1.mp3`)
</ParamField>

<ParamField body="contentType" type="string" required>
  MIME type of the file. Common types include:

  * `audio/mpeg` - MP3 audio files
  * `video/mp4` - MP4 video files
  * `image/jpeg` - JPEG images
  * `image/png` - PNG images
  * `audio/wav` - WAV audio files
</ParamField>

## Response

<ResponseField name="success" type="boolean">
  Indicates whether the request was successful
</ResponseField>

<ResponseField name="data" type="object">
  <Expandable title="properties">
    <ResponseField name="signedUrl" type="string" required>
      The temporary pre-signed URL for file upload. Use this URL in a PUT request to upload your file. Expires after 24 hours.
    </ResponseField>

    <ResponseField name="url" type="string" required>
      The permanent CloudFront CDN URL for accessing the uploaded file. Use this URL to reference or download the file in subsequent API calls.
    </ResponseField>

    <ResponseField name="key" type="string" required>
      The unique storage key identifying the file location in the storage system.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json 200 - Success theme={null}
  {
    "success": true,
    "data": {
      "signedUrl": "https://pictory-api-prod.s3.us-east-2.amazonaws.com/public/teams/aa46778d-7965-46e0-967d-b48ee5d6ead9/users/Google_100807387384973267064/47ca856b-a15a-41b8-9a4b-88386cfa77d9/test-sample.mp3?Content-Type=audio%2Fmpeg&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIA2GVAALU3KROYHJW4%2F20251223%2Fus-east-2%2Fs3%2Faws4_request&X-Amz-Date=20251223T061537Z&X-Amz-Expires=86400&X-Amz-Security-Token=...",
      "url": "https://dg516uv4r33q1.cloudfront.net/public/teams/aa46778d-7965-46e0-967d-b48ee5d6ead9/users/Google_100807387384973267064/47ca856b-a15a-41b8-9a4b-88386cfa77d9/test-sample.mp3",
      "key": "public/teams/aa46778d-7965-46e0-967d-b48ee5d6ead9/users/Google_100807387384973267064/47ca856b-a15a-41b8-9a4b-88386cfa77d9/test-sample.mp3"
    }
  }
  ```

  ```json 401 - Unauthorized theme={null}
  {
    "message": "Unauthorized"
  }
  ```

  ```json 500 - Internal Server Error theme={null}
  {
    "error": "Internal Server Error",
    "message": "An unexpected error occurred"
  }
  ```
</ResponseExample>

## Important Notes

<Note>
  **Signed URL Expiration**: The signed URL automatically expires after 24 hours (86400 seconds). Upload your file promptly after receiving the URL to avoid expiration.
</Note>

<Note>
  **Content-Type Matching**: The `Content-Type` header in your upload request must exactly match the `contentType` specified when generating the signed URL, otherwise the upload will fail.
</Note>

<Tip>
  After successfully uploading your file, use the permanent `url` field from the response to access or reference the file in future API calls. Store this URL for later use.
</Tip>

## Additional Resources

For more information on working with pre-signed URLs, refer to the [AWS S3 Pre-signed URL documentation](https://docs.aws.amazon.com/AmazonS3/latest/API/s3_example_s3_Scenario_PresignedUrl_section.html).
