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.

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-databody. Each file goes in its own uniquely named part,files[0],files[1]and so on, and each part needs aContent-Dispositionheader with a filename. - Put the non-file fields, such as
content, in onepayload_jsonpart as JSON, or send them as separate form fields. - A message needs at least one of
content,embeds,components,fileorpoll.contentholds up to 2000 characters. - Add
?wait=trueto get the created message back. Without it, Discord answers204 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.
| Limit | Value |
|---|---|
| File size | 20 MiB per file by default; may be higher with Nitro or the server's Boost Tier |
content | Up to 2000 characters |
embeds | Up to 10 embed objects |
| Attachments shown inside an embed | Only .jpg, .jpeg, .png, .webp and .gif |
Embed video field | Can'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
2xxwithin 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[]carriesurl,content_typeandsize_bytes, so you can choose between attaching and linking before you download anything. media.sume.comURLs 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
- fal MCP server: setup for Claude Code, Cursor, and billing
fal's MCP server runs at mcp.fal.ai/mcp with a fal API key or sign-in. The server is free; model runs bill to your fal account at API prices.
- Send push notifications using the Firebase API for AI video
Send a push with the FCM HTTP v1 API from your server when the video job's webhook arrives: POST messages:send with a short-lived OAuth 2.0 token.
- Firebase scheduled functions: call a paid API once a day
Declare a Firebase scheduled function with onSchedule, a cron and a timeZone, keep the API key in secrets, and key each paid call to scheduleTime.
- Setting up API calls in FlutterFlow for AI video
Set up a FlutterFlow API call with a Bearer header, make it private so it runs as a Firebase Cloud Function, and poll the video job with a second call.
Written by Sume