跳到內容

Send messages with a webhook

本頁內容尚未翻譯。

Status Stable · Last verified 2026-07-11 · API v10 · Sources Execute Webhook, Rate Limits

Once you have a URL, you send messages by POSTing to it (the “Execute Webhook” endpoint). No auth header — the token is in the URL.

Terminal window
curl -X POST "$DISCORD_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d '{ "content": "Hello, channel!" }'

Response: 204 No Content. Add ?wait=true to the URL to instead receive 200 with the created message object (useful when you need the message id).

{
"username": "Atlas Notifier",
"avatar_url": "https://example.com/avatar.png",
"content": "Deploy finished.",
"embeds": [
{
"title": "Build #128 succeeded",
"description": "All checks passed on `main`.",
"url": "https://example.com/ci/128",
"color": 5793266,
"fields": [
{ "name": "Duration", "value": "3m 12s", "inline": true },
{ "name": "Commit", "value": "`a1b2c3d`", "inline": true }
],
"footer": { "text": "discord-platform-atlas" },
"timestamp": "2026-07-11T12:00:00.000Z"
}
]
}
  • color is a decimal integer (hex 0x5865F2 = 5793266).
  • timestamp must be ISO 8601.
  • username/avatar_url override the webhook’s defaults per message.

Use multipart/form-data: a payload_json part plus one or more files[n] parts. You can reference an uploaded file inside an embed via attachment://filename.

Terminal window
curl -X POST "$DISCORD_WEBHOOK_URL" \
-F 'payload_json={"content":"Log attached","embeds":[{"image":{"url":"attachment://chart.png"}}]}' \
-F 'files[0]=@chart.png'
POST {DISCORD_WEBHOOK_URL}?thread_id=THREAD_ID

For a forum/media channel, either target an existing thread with thread_id, or create a new post by including thread_name in the JSON body.

By default Discord parses @everyone, roles, and users in content. To avoid surprise pings, set allowed_mentions explicitly:

{
"content": "Heads up <@&ROLE_ID>",
"allowed_mentions": { "parse": [], "roles": ["ROLE_ID"] }
}

"parse": [] suppresses all mentions; then opt back in per type. This is a common source of accidental mass-pings — set it deliberately.

  • Edit: PATCH {url}/messages/{message.id} with the fields to change.
  • Delete: DELETE {url}/messages/{message.id}.
  • You need the message id — send with ?wait=true to get it back.
Thing Limit
content length 2000 characters
Embeds per message 10
Total characters across all embeds 6000
Embed title 256
Embed description 4096
Embed fields 25
Field name / value 256 / 1024
Embed footer.text / author.name 2048 / 256
Attachment size Depends on the server’s boost tier (base ~10 MiB / 25 MB)

[!NOTE] Verified (2026-07-11) content “up to 2000 characters” and “up to 10 embed objects” are from Execute Webhook; the embed sub-limits and the 6000-character combined total (across all title, description, field.name, field.value, footer.text, and author.name fields of every embed on the message) are from the Embed Limits. Attachment size is not a fixed number — it scales with the server’s boost tier, so it stays an observation.

  • A webhook is limited to roughly 30 messages per minute per webhook, on top of Discord’s global limits. Exact values are not guaranteed — do not hard-code them.
  • On 429, read the JSON retry_after (seconds) and the X-RateLimit-* response headers, wait, then retry.
  • Design for backpressure: batch related updates into fewer messages, and prefer editing a status message over posting a new one each time.

See Rate Limits and the runnable webhook-minimal example, which handles 429 correctly.

Webhooks can also send interactive Components V2 layouts by setting the message flag IS_COMPONENTS_V2 (1 << 15 = 32768). That flag disables content and embeds for the message in favor of component containers, and it cannot be removed once the message is sent. This is an advanced path — see Interactions → Components before using it.