Uploads
Analyze your own video files instead of a platform URL.
Three steps: get a presigned URL, PUT the file to it, then create a job with the returned key. On every plan; size,
format and how many unused uploads you can hold are on Limits.
1. Request a presigned URL
POST /v1/uploads/presign
Returns HTTP 200 with the put_url to upload to and the key to create the job with.
| Prop | Type | Description |
|---|---|---|
| content_type | string | One of video/mp4, video/quicktime or video/webm. |
| size_bytes | integer | Exact file size in bytes. Up to 500 MB. |
curl -X POST https://api.netraflow.com/v1/uploads/presign \
-H "Content-Type: application/json" \
-H "X-Api-Key: sk_live_your_key_here" \
-d '{
"content_type": "video/mp4",
"size_bytes": 18234112
}'{
"data": {
"put_url": "https://<upload-host>/uploads/...?X-Amz-Signature=...",
"key": "uploads/ten_abc123/8b1d6c1e-2f4a-4c57-9d3e-5a7b1c9e0f42.mp4"
},
"meta": { "request_id": "req_xyz789" }
}2. Upload the file
PUT the raw bytes to put_url with the Content-Type you presigned, within 10 minutes. The body must be exactly
size_bytes long.
curl -X PUT "$PUT_URL" \
-H "Content-Type: video/mp4" \
--data-binary @my-video.mp43. Create the job
Pass upload_key instead of url, plus upload_filename for the video title.
curl -X POST https://api.netraflow.com/v1/jobs \
-H "Content-Type: application/json" \
-H "X-Api-Key: sk_live_your_key_here" \
-d '{
"upload_key": "uploads/ten_abc123/8b1d6c1e-2f4a-4c57-9d3e-5a7b1c9e0f42.mp4",
"upload_filename": "my-video.mp4",
"capabilities": ["transcription"]
}'{
"data": {
"job_id": "job_abcdefghij123456",
"status": "pending",
"url": "uploads/ten_abc123/8b1d6c1e-2f4a-4c57-9d3e-5a7b1c9e0f42.mp4",
"platform": "upload",
"capabilities": ["transcription"],
"language": null,
"video_title": "my-video.mp4",
"video_duration_seconds": null,
"video_thumbnail_url": null,
"credits_estimated": 2,
"credits_charged": null,
"processing_seconds": null,
"return_proof": true,
"follow_id": null,
"created_at": "2026-04-03T12:00:00.000Z",
"started_at": null,
"completed_at": null
},
"meta": { "request_id": "req_xyz789" }
}The job has platform: "upload" and your upload_key as its url, and is like any other job from there. Send both
url and upload_key, neither, or a key that isn't yours, and it is VALIDATION_FAILED (422). Batches take uploads in their uploads array.
Reuse. Any number of jobs can use the same key while the file exists, each charged as usual. Pass the first job as
from_job to reuse its work.
Deletion. A file is deleted 2 days after upload at most, sooner once no job needs it: a day after its last job
completed, or within seconds when it failed or was cancelled. A job on a deleted file fails with UPLOAD_NOT_FOUND;
one on a file that isn't a video fails with EXTRACTION_FAILED. Neither is charged.