Post to a Discord channel
Discord embeds turn a plain notification into a card with a title, color, fields and a thumbnail, but wiring that up reliably from a backend usually means maintaining a bot you didn't want to host. This endpoint posts the embed for you and tracks it like any other task.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
For communities and teams running on Discord, not just gamers
Discord stopped being just a gaming chat app years ago; plenty of open-source projects, indie SaaS teams and online communities now run their entire operational feed through it. notify.discord is for the moment a project needs to post a release note, a build status or a community alert into a channel without standing up a persistent bot process just to make one HTTP call.
What actually gets posted
POST /notify/discord accepts a webhook target, a plain message and an optional embed object — title, description, color, fields and a thumbnail or image URL — matching Discord's own embed structure, so anything you already know about formatting embeds carries over directly. We handle delivery, retries on rate limits or transient failures, and report back whether the post landed.
Embeds exist because plain text doesn't scale
Discord introduced embeds specifically because plain-text bot messages became unreadable once servers started using bots for release announcements, moderation logs and status updates all in the same channel — a colored side bar and structured fields let someone tell at a glance what kind of message they're looking at before reading a word. We lean on that same structure rather than inventing our own formatting layer.
Fits quietly into existing automation
Because the call is async, a CI pipeline, a monitoring script or a form handler can fire POST /notify/discord and move on immediately, with the actual post happening independently. It's a natural pairing with alert routing when Discord is one of several channels a given event might need to reach, or with the digest endpoint when you want a daily rollup instead of one embed per event.
How you know it worked
Delivery status, including Discord's rate-limit responses if the target webhook is throttled, comes back through a signed webhook or a signed link valid for 24 hours. A malformed embed or an invalid webhook URL returns a clear error rather than a silent no-op, so debugging a broken integration doesn't mean staring at an empty channel wondering what happened.
What you can do with it
Release and changelog announcements
An open-source project's CI posts a formatted embed with version number and changelog highlights to the community's #releases channel on every tag.
Community moderation alerts
An automated moderation system posts an embed with the flagged message, author and reason to a private mod-log channel for quick review.
Game server and bot status
A self-hosted game server posts player count and uptime embeds to a status channel on a schedule, no bot process required.
Support ticket notifications
A helpdesk integration posts new ticket embeds with priority color-coding to an internal support channel the moment a ticket is created.
FAQ
How do I post a rich embed to Discord with this API?
Send an embed object with title, description, color and fields in the body of POST /notify/discord, matching Discord's own embed structure, and it's delivered to the channel behind your webhook.
Do I need to host a Discord bot to use this?
No, this is webhook-based delivery, not a bot connection, so there's no persistent process to host or Discord application to register.
Is notify.discord free to use?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
What does each Discord notification cost?
It's $0.002 per POST /notify/discord request, and a failed delivery, after three automatic retries, is never charged.
What happens if Discord rate-limits the webhook?
Rate-limit responses are handled with automatic retry and backoff, and if delivery ultimately still fails you get the specific error back instead of a silent drop.
Can I send both plain text and an embed in one message?
Yes, the request accepts a plain-text message alongside the embed object, matching how Discord itself renders combined messages.
Can I use this to post to multiple Discord servers?
Yes, each call targets a specific webhook URL, so different calls can point at different servers or channels independently.
Is embed content retained after it's posted?
No, message and embed payloads are deleted after the stated retention period and are never used for training.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/notify/discord \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"input":"…"}'const res = await fetch("https://api.kit.forhosting.com/notify/discord", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"input": "…"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/notify/discord",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"input": "…"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/notify/discord", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"input":"…"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"input":"…"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/notify/discord", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"input": "…"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "notify.discord",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |