REST API
Upload and share files
This tutorial takes one local file named demo.mp4 and turns it into a working share URL. Complete the steps in order; each response supplies a value used by the next request.
Create and save an API key
Open Developer settings, select uploads:write, files:read, shares:write, and shares:read, then create the key. Copy it now—the full secret is shown only once.
Available scopes: uploads:write, files:read, shares:write, and shares:read.
Prepare your terminal
Put the key in an environment variable so it does not appear in every command or in your shell history. Replace the placeholder before pressing Enter.
read -s VIDEO2URL_API_KEY
echo "key loaded"Create an upload job
Tell Video2URL the exact filename, MIME type, and byte size. This returns a temporary R2 upload URL; it does not upload the video yet.
POST /api/v1/uploads
curl -sS -X POST https://video2url.com/api/v1/uploads \
-H "Authorization: Bearer $VIDEO2URL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"filename":"demo.mp4","mimeType":"video/mp4","sizeBytes":1048576}'export UPLOAD_ID="paste data.uploadId here"
export UPLOAD_URL="paste data.upload.url here"Send the video bytes
Upload demo.mp4 directly to the temporary URL. Do not add the Video2URL API key to this PUT request. Use the Content-Type returned by the create-upload response. Upload the raw file to the presigned URL using the returned content type.
curl --fail-with-body -X PUT "$UPLOAD_URL" \
-H "Content-Type: video/mp4" \
-H "If-None-Match: *" \
--data-binary @demo.mp4Complete and verify the upload
After PUT succeeds, tell Video2URL to verify the stored object and create the file record. Do not call this step before the PUT finishes.
POST /api/v1/uploads/{uploadId}/complete · GET /api/v1/uploads/{uploadId}
curl -sS -X POST "https://video2url.com/api/v1/uploads/$UPLOAD_ID/complete" \
-H "Authorization: Bearer $VIDEO2URL_API_KEY"export FILE_ID="paste data.file.fileId here"JavaScript & Python
Create the narrowest key you need. Rotate by creating and deploying a replacement before revoking the old key. If paid access ends, keys stay saved but calls pause; renewing an eligible plan restores access.
const response = await fetch('https://video2url.com/api/v1/uploads', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.VIDEO2URL_API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ filename: 'demo.mp4', mimeType: 'video/mp4', sizeBytes: file.size }),
});
const created = await response.json();
if (created.data.upload.contractVersion !== 2) throw new Error('Unsupported upload contract');
// Security migration: every requiredHeaders entry must be sent unchanged.
await fetch(created.data.upload.url, { method: 'PUT', headers: { ...created.data.upload.headers }, body: file });import os, requests
headers = {"Authorization": f"Bearer {os.environ['VIDEO2URL_API_KEY']}"}
created = requests.post("https://video2url.com/api/v1/uploads", headers=headers, json={"filename": "demo.mp4", "mimeType": "video/mp4", "sizeBytes": 1048576})
created.raise_for_status()
with open("demo.mp4", "rb") as video:
upload = created.json()["data"]["upload"]
requests.put(upload["url"], headers=upload["headers"], data=video).raise_for_status()