Discord¶
The daemon delivers PU and @Intel notices to a player's personal Discord channel via
their @prfwebhook, and records every send in a delivery log. This page covers sending a
message and reading back the delivery outcomes. Sending reaches the network, so the
example uses ?dryRun=true — a pure preview that POSTs nothing and writes no log record.
Sending needs discord.send; reading the log needs log.read. Every example runs
against a live daemon — see how the reference is tested.
Routes¶
| Method | Path | Cmdlet | Cap | Write |
|---|---|---|---|---|
| POST | /discord/send |
Send-NerthusDiscordMessage |
discord.send |
— |
| GET | /discord/deliveries |
Get-NerthusDiscordDeliveryLog |
log.read |
— |
Cap is the required capability (— = public, no token); Write (✓) marks routes that pass the write gate; a — in Cmdlet is reached directly, no wrapper. Paths are relative to /v1/api; the cross-cutting contract — middleware, envelopes, status codes — is on the API reference index.
POST /discord/send is not Write-flagged — its only write is private delivery state, so it stays operable in read-only mode.
Preview a send without reaching Discord¶
POST /v1/api/discord/send posts a message to a webhook. With ?dryRun=true it returns
200 { Delivered: false, Result: "WHATIF" }, echoes the entity and message, and makes
no HTTP request — proven by the follow-up: the delivery log stays empty. Here the fixture
Gracz Stefan and his webhook.
await fetch("https://evocation.nerthus.pl/v1/api/discord/send?dryRun=true", {
method: "POST",
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}` },
body: JSON.stringify({
webhook: "https://discord.com/api/webhooks/1001/PLACEHOLDER",
entity: "Stefan",
message: "Test",
}),
}).then((r) => r.json());
Response 200:
The delivery log¶
GET /v1/api/discord/deliveries returns the { count, items } envelope of actual send
outcomes, newest first. Filter with ?operation= (message, Intel). A dry run never
records, so on a fresh daemon the log is empty.
Response 200: