Discord webhook send file: attach a video with files[0]

Yes: POST multipart/form-data to the webhook URL with the file as files[0] and the text in payload_json. Over 20 MiB by default, post the link.

5 min readSume
All posts

Yes, a Discord webhook can send a file. POST to the webhook URL as multipart/form-data, put the file in a part named files[0] with a filename, and put the message text as JSON in a payload_json part. Discord's default upload limit is 20 MiB per file, so check the video's size first and post its link in content when it's over the limit.

Discord facts come from its Webhook Resource, API Reference, Opcodes and Status Codes and Intro to Webhooks pages; Sume facts come from Run webhooks and Runs and results. All were read on 2026-09-28. Sume has no Discord bot or connector: your server receives Sume's webhook for a finished video, then calls Discord. A bot that starts the video from a slash command is covered in Discord bot AI video generation.

How do I send a file with a Discord webhook?

Create the webhook in your server's settings under Integrations, pick the channel it posts to, and copy the webhook URL. Then send an HTTP POST to that URL, Discord's Execute Webhook endpoint:

  • Use a multipart/form-data body. Each file goes in its own uniquely named part, files[0], files[1] and so on, and each part needs a Content-Disposition header with a filename.
  • Put the non-file fields, such as content, in one payload_json part as JSON, or send them as separate form fields.
  • A message needs at least one of content, embeds, components, file or poll. content holds up to 2000 characters.
  • Add ?wait=true to get the created message back. Without it, Discord answers 204 No Content, and a message that wasn't saved doesn't return an error.
// Node 18+. DISCORD_WEBHOOK_URL is a secret: anyone holding it can post.
const LIMIT = 20 * 1024 * 1024; // Discord's default per-file limit, 20 MiB

async function postVideo(videoUrl, sizeBytes) {
  const hook = `${process.env.DISCORD_WEBHOOK_URL}?wait=true`;
  let res;
  if (sizeBytes > LIMIT) {
    res = await fetch(hook, { // too big to attach: send the link as JSON
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ content: `Your video is ready: ${videoUrl}` }),
    });
  } else {
    const video = await fetch(videoUrl); // a public media.sume.com URL
    if (!video.ok) throw new Error(`download answered ${video.status}`);
    const form = new FormData();
    form.append("payload_json", JSON.stringify({ content: "Your video is ready" }));
    form.append("files[0]", await video.blob(), "video.mp4");
    res = await fetch(hook, { method: "POST", body: form });
  }
  if (!res.ok) throw new Error(`Discord answered ${res.status}`);
  return res.json(); // the created message, because of wait=true
}

What is the Discord webhook file upload limit?

The limit applies to each file in a request. Discord's reference sets the default at 20 MiB, and it may be higher depending on Nitro status or the server's Boost Tier. Discord's JSON error code 40005 reads "Request entity too large. Try sending something smaller in size."

An MP4 can't go inside an embed either: an uploaded file can be used in an embed only if it's one of the image types below, and a webhook can't set an embed's video field. Attach the video as a file when it fits, and post its link when it doesn't.

From Discord's API Reference and Webhook Resource pages, read 2026-09-28.
LimitValue
File size20 MiB per file by default; may be higher with Nitro or the server's Boost Tier
contentUp to 2000 characters
embedsUp to 10 embed objects
Attachments shown inside an embedOnly .jpg, .jpeg, .png, .webp and .gif
Embed video fieldCan't be set on a webhook embed

Is a Discord webhook URL a secret?

Yes, treat it like a password. Discord says webhooks do not require a bot user or authentication to use, and the calls that read, modify or delete a webhook with its token don't require authentication either. Anyone holding the URL can post as the webhook, or delete it.

Keep the URL in a server-side secret store, never in browser code, a mobile app or a public repository. If it leaks, delete the webhook and create a new one.

How do I post a Sume video when it's ready?

Call Discord from the server that receives Sume's webhook, after you've verified it:

  • Sume sends one signed POST when a Format run completes or fails. Verify the HMAC-SHA256 signature over the raw body, record the event, and answer 2xx within the 10-second attempt window before you call Discord, because a slow endpoint gets retried. Signed webhooks for Sume video runs covers the check.
  • Each entry of payload.artifacts[] carries url, content_type and size_bytes, so you can choose between attaching and linking before you download anything.
  • media.sume.com URLs are durable and public to anyone holding them. The download needs no API key, and a posted link doesn't expire.
  • Dedupe on the envelope's request_id, which repeats on every retry, so a retried delivery doesn't post twice.
  • Don't register the Discord URL as Sume's webhook_url. Sume's POST carries its run receipt, not a Discord message.

Sources

Related posts

More in Integrations

All Integrations posts

Written by Sume