App webhooks
An app webhook is a per-channel URL your CI runner, monitoring tool, or external service can POST to in order to drop a message into a GameVox channel. No gateway session required. Messages post as your bot user, with the bot's avatar and username.
Limits
- 50 webhooks per application.
- Name: 1–80 characters.
- Content: 1–4000 characters per message.
- One webhook = one channel. Creating a webhook requires the
manage_serverpermission in the channel's server.
Token format
WH.{8-char prefix}.{base64 random}
example: WH.aB7xZ2k1.q9F7v1NkN3J2Wm8L6PpV5cU0Yr1zQbXa The full token is shown exactly once, at create time. We store only the bcrypt hash plus the prefix and last 4 characters for display. If you lose a token, delete the webhook and create a new one.
Creating a webhook (portal)
Open your application → Webhooks tab → New Webhook. Pick a server you can manage, pick a channel, give it a name. The reveal modal shows the full token and the ready-to-paste execute URL. Copy it before dismissing; the portal will never show it again.
Endpoints
Two auth modes: bot token for management, URL token for execute.
Bot-token auth (management)
GET /channels/{channel.id}/webhooks
POST /channels/{channel.id}/webhooks
GET /guilds/{guild.id}/webhooks
GET /webhooks/{webhook.id}
PATCH /webhooks/{webhook.id}
DELETE /webhooks/{webhook.id} URL-token auth (execute + edit)
POST /webhooks/{webhook.id}/{token}
GET /webhooks/{webhook.id}/{token}
PATCH /webhooks/{webhook.id}/{token}
DELETE /webhooks/{webhook.id}/{token}
PATCH /webhooks/{webhook.id}/{token}/messages/{message.id}
DELETE /webhooks/{webhook.id}/{token}/messages/{message.id}
For URL-token routes there is no Authorization
header. The token in the URL path is the auth. Treat
the URL like a secret.
Execute request
JSON body:
POST https://api.gamevox.com/webhooks/{webhook.id}/{token}
Content-Type: application/json
{
"content": "Build #4811 passed on production.",
"embeds": [
{
"title": "CI green",
"url": "https://ci.example.com/builds/4811",
"description": "42 tests, 0 failures.",
"color": 3066993
}
]
} multipart/form-data body (for attachments):
Content-Type: multipart/form-data; boundary=xyz
--xyz
Content-Disposition: form-data; name="payload_json"
{ "content": "See screenshot", "embeds": [ ... ] }
--xyz
Content-Disposition: form-data; name="files[0]"; filename="crash.png"
Content-Type: image/png
...binary...
--xyz-- Response (both content types):
{
"id": "1199283740192847400",
"channel_id": "1199283740192847000",
"content": "Build #4811 passed on production.",
"embeds": [ ... ],
"attachments": [ ... ],
"timestamp": "2026-05-21T15:42:09Z"
} What's supported
- Content: plain text, 1–4000 characters.
- Embeds: full Discord embed shape (title, description, url, color, timestamp, footer, image, thumbnail, author, fields). Multiple embeds per message allowed.
- Attachments: upload files via
multipart/form-datawith apayload_jsonpart; the response includes CDN URLs. - Reply targeting: pass
message_referenceinpayload_json. ?wait=true: implicit; the response is always the resolved message.- Edit / delete:
PATCH/DELETEon/webhooks/{id}/{token}/messages/{message.id}mirror Discord. - Username / avatar overrides: not supported. Messages always post as the application's bot user.
Errors
401: token missing, malformed, or doesn't match.404: webhook deleted, or id doesn't exist.400: emptycontentand no embeds/attachments, orcontentlonger than 4000 characters.405: verb not supported on this route.413: attachment exceeds the per-file size limit.
Rotating
There is no rotate-in-place endpoint in v1. Delete the webhook and create a new one. The old token stops working immediately on delete (the execute path excludes soft-deleted rows).
Differences from Discord
- Webhooks are owned by the application, not by a server admin. Deleting the channel does not delete the webhook row; the next execute returns
404from the channel join in the lookup. - No
username/avatar_urloverrides per request. Identity is fixed to the bot user. - Per-channel webhook cap is not enforced; the cap is per-application (50).
- Auth is verified with bcrypt, so token compare is intentionally slow. Don't hammer the endpoint in tight loops.
- Self-hosted servers: webhooks aren't routed to self-hosted boxes. All webhook endpoints return
404for self-hosted guild targets. See Self-hosted docs.