Browse developer docs

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.

1

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.

Expected result:You have a secret that begins with the Video2URL key prefix. Keep it private.
2

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.

Terminal
read -s VIDEO2URL_API_KEY
echo "key loaded"
Expected result:The command prints key loaded, not the secret itself.
3

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
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}'
Expected result:A JSON response containing data.uploadId and data.upload.url. Save both values for the next steps.
Save response values
export UPLOAD_ID="paste data.uploadId here"
export UPLOAD_URL="paste data.upload.url here"
4

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 · PUT
curl --fail-with-body -X PUT "$UPLOAD_URL" \
  -H "Content-Type: video/mp4" \
  -H "If-None-Match: *" \
  --data-binary @demo.mp4
Expected result:The upload server returns HTTP 200. An empty response body is normal.
5

Complete 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
curl -sS -X POST "https://video2url.com/api/v1/uploads/$UPLOAD_ID/complete" \
  -H "Authorization: Bearer $VIDEO2URL_API_KEY"
Expected result:The response contains data.file.fileId. Save FILE_ID; it identifies the completed file.
Save FILE_ID
export FILE_ID="paste data.file.fileId here"
6

Create the final share URL

Create an unlisted link from FILE_ID. Unlisted means anyone with the URL can open it, but it is not placed in a public directory.

  • Title is optional.
  • Password is optional.
  • Visibility is optional.
  • Visibility defaults to unlisted.

POST /api/v1/shares · GET / DELETE /api/v1/shares/{shareId}

curl
curl -sS -X POST https://video2url.com/api/v1/shares \
  -H "Authorization: Bearer $VIDEO2URL_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{"fileId":"$FILE_ID","visibility":"unlisted"}"
Expected result:The response contains the share record and URL. Open SHARE_URL in a private browser window to verify it.
Open SHARE_URL
export SHARE_URL="paste the returned share URL here"
open "$SHARE_URL" # macOS; use xdg-open on Linux

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.

JavaScript
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 });
Python
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()