Skip to main content

Add a file from a link

Give Videas a link — a presigned URL to your bucket, for instance — and it downloads the file into your library in the background, from four fixed addresses you can allow.

If the file is already online — in a bucket, on a CDN, on your media server — you don’t need to send it: give us its link, and we download it into your library in the background. It is the same resource as a file you send, POST /v1/uploads, with source_url in place of size_bytes.

curl -X POST https://api.videas.com/v1/uploads \
  -H "Authorization: Bearer $VIDEAS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workspace_id": "0192a6b1-7c3e-7d40-9a51-3f0e2b6c8d10",
    "source_url": "https://media.example.com/exports/lecture.mp4?X-Amz-Expires=86400&X-Amz-Signature=…",
    "sha256": "5e8f4c0d9b1a…",
    "external_ref": "course-42/lecture-1"
  }'

The key, the workspace and the optional name, description, language and external_ref are as for a file you send. Then:

Field
source_url Required. The link to the file.
filename Optional. Without it, the file is named from the server’s Content-Disposition, else from the link’s last segment.
sha256 Optional. The file’s SHA-256, as 64 hexadecimal characters: the file we download must match it.

The answer is a 201 — and there is nothing to send: no address, no token.

{
  "id": "0192a6c0-1e2f-7a34-9b56-7c8d9e0f1a2b",
  "asset_id": "0192a6c0-1e2b-7c01-8d23-4e5f6a7b8c9d",
  "workspace_id": "0192a6b1-7c3e-7d40-9a51-3f0e2b6c8d10",
  "source": "link",
  "status": "pending",
  "size_bytes": null,
  "received_bytes": 0,
  "upload_url": null,
  "max_put_bytes": null,
  "expires_at": null,
  "source_url": "https://media.example.com/exports/lecture.mp4",
  "failure": null,
  "created_at": "2026-09-26T09:20:03Z",
  "updated_at": "2026-09-26T09:20:03Z",
  "finished_at": null,
  "upload_token": null
}
  • http or https, on the scheme’s own port: 80 for http, 443 for https.
  • No user name or password in it — https://user:secret@… is refused.
  • On a public server: not localhost, not a private or reserved address.
  • The file itself, not a page about it. A YouTube, Vimeo or Dailymotion page is refused at once: it is a player, not a file, and POST /v1/assets creates the asset that plays it. A web page (text/html) where the file should be fails not_a_file.
  • At most 10 GiB.

What can be seen in the link is refused at once, with a 400 naming the reason. The rest is found by the download.

How we download it: GET requests carrying User-Agent: Videas-Fetch/… (+https://videas.com/bot; support@videas.com), at most five redirects followed — never from https to http — and a download that broke off resumed with a Range request from where it stopped. A server that ignores Range has the file read again from the start.

Allow our addresses

Links are fetched from these four addresses, and from no others. If your server, your firewall or your bucket’s policy only answers known addresses, allow all four — either family may be used:

Addresses
IPv4 193.104.118.42, 193.104.118.43
IPv6 2a12:3440:102::3:42, 2a12:3440:102::3:43

Warning: allowing these addresses is not a credential. They fetch the links of every Videas customer, so a file readable by these addresses alone is readable by anyone able to hand us its URL. Keep the link signed — a presigned URL — and use the addresses to narrow access, never to open it.

  • It is sealed — encrypted — while the download needs it, and erased when the upload ends.
  • It is never shown back whole: source_url in our answers is your link without its query, so without its signature. Our logs name it the same way.
  • Sign it for long enough. The download may wait its turn and be retried from where it stopped; a signature that expired meanwhile fails the upload refused. Sign it for longer than the download may take, retries included.

Check the file with sha256

Give the file’s SHA-256 and we check the file against it once it is downloaded. A copy that does not match is downloaded once more, from the start; if it still does not match, the upload fails checksum_mismatch. Over plain http, it is the only thing that proves the file is the one you meant.

Follow the download

There is no notification yet: poll GET /v1/uploads/{id}.

status Meaning
pending Queued: the download has not started.
receiving Downloading. received_bytes grows, and size_bytes appears once the server has said.
completed The file is stored. The asset goes on to processing, then ready.
failed The download failed, and failure.code says why.
cancelled Given up on with DELETE /v1/uploads/{id} — or the asset was deleted before the file arrived.
expired Rare: a download nobody was fetching any more.

failed, cancelled and expired are final, and the asset then ends error. A failed upload says why:

{
  "status": "failed",
  "failure": {
    "code": "refused",
    "message": "the link's server refused the request: answered 403 Forbidden"
  }
}

Branch on failure.code; message is for a person and may change.

failure.code What happened What to do
address_refused We do not connect to where the link leads: an address of ours, or a private or reserved one. Over https, it is also the answer when the connection could not be opened, twice in a row — a name that does not resolve, a server that refuses us. Check the link’s host, and that it accepts connections from our addresses.
unreachable No answer, after trying again for a while: over http, a name that does not resolve or a failed connection; a TLS failure or a timeout; a server that kept answering 5xx or 429. Check that the server is up and reachable from our addresses.
not_found 404 or 410. Fix the link.
refused Any other 4xx — typically a presigned link that expired — or a redirect we do not follow: a sixth one, or from https to http. Sign the link for longer, or link the final address.
not_a_file A web page where the file should be. Link the file itself.
too_large Larger than 10 GiB. —
interrupted The download broke off more times than it is retried. Check the server’s stability, then try again.
checksum_mismatch Downloaded twice, and twice not the sha256 you gave. Check the digest, or the file behind the link.

Each is final: once the cause is fixed, open a new upload. A code you don’t know is a failure your code does not handle yet — the list may grow.

Limits and retries

  • At most 10 GiB per file.
  • An organization may only have so many links waiting or downloading at once. Past that, the request is refused with a 429 and Retry-After: wait that many seconds, then send it again. An upload that has ended frees its place.
  • Retrying after a timeout or a 5xx works as for a file you send: set external_ref, and look it up before sending again. A link found that way is already being downloaded — don’t send it again.
  • To give up, DELETE /v1/uploads/{id}: the download stops at its next part, the link is forgotten, and the asset ends error.

Next steps