Skip to main content
POST
/
pictoryapis
/
v1
/
media
/
generateurl
Generate Signed URL for File Upload
curl --request POST \
  --url https://api.pictory.ai/pictoryapis/v1/media/generateurl \
  --header 'Authorization: <authorization>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "fileName": "<string>",
  "contentType": "<string>"
}
'
import requests

url = "https://api.pictory.ai/pictoryapis/v1/media/generateurl"

payload = {
"fileName": "<string>",
"contentType": "<string>"
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "application/json"
}

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

print(response.text)
const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({fileName: '<string>', contentType: '<string>'})
};

fetch('https://api.pictory.ai/pictoryapis/v1/media/generateurl', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://api.pictory.ai/pictoryapis/v1/media/generateurl",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'fileName' => '<string>',
'contentType' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: application/json"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

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

func main() {

url := "https://api.pictory.ai/pictoryapis/v1/media/generateurl"

payload := strings.NewReader("{\n \"fileName\": \"<string>\",\n \"contentType\": \"<string>\"\n}")

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

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

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

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

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://api.pictory.ai/pictoryapis/v1/media/generateurl")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"fileName\": \"<string>\",\n \"contentType\": \"<string>\"\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://api.pictory.ai/pictoryapis/v1/media/generateurl")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"fileName\": \"<string>\",\n \"contentType\": \"<string>\"\n}"

response = http.request(request)
puts response.read_body
{
  "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"
  }
}
{
  "message": "Unauthorized"
}
{
  "error": "Internal Server Error",
  "message": "An unexpected error occurred"
}

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.
You need a valid API key to use this endpoint. Get your API key from the API Access page in your Pictory dashboard.

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.
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
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"]
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;

Step 2: Upload Your File

Use the signed URL to upload your file directly to storage via a PUT request.
curl --location --request PUT 'SIGNED_URL_FROM_STEP_1' \
  --header 'Content-Type: audio/mpeg' \
  --data-binary '@/path/to/your/sample1.mp3'
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!")
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!');
}

Request

Headers

Authorization
string
required
API key for authentication (starts with pictai_)
Authorization: YOUR_API_KEY

Body Parameters

fileName
string
required
Name of the file to be uploaded (e.g., sample1.mp3)
contentType
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

Response

success
boolean
Indicates whether the request was successful
data
object
{
  "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"
  }
}
{
  "message": "Unauthorized"
}
{
  "error": "Internal Server Error",
  "message": "An unexpected error occurred"
}

Important Notes

Signed URL Expiration: The signed URL automatically expires after 24 hours (86400 seconds). Upload your file promptly after receiving the URL to avoid expiration.
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.
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.

Additional Resources

For more information on working with pre-signed URLs, refer to the AWS S3 Pre-signed URL documentation.