Skip to content

Event catalogue

Subscribe a webhook endpoint to one or more of these events on the Webhooks dashboard. The payload shape under data is documented per event below; the outer envelope (id, type, created_at, guild_id, livemode) is the same for every event — see Webhooks.

Each event lists where it originates:

  • bot — emitted by the Discord bot as things happen in your server (member joins, ticket buttons, automod hits, …). Bot-emitted events are queued durably and dispatched within about a minute.
  • web — emitted by the dashboard / appeal portal.
  • api — emitted by REST API writes (/api/v1/*).

Bot-emitted events include an occurred_at ISO timestamp in data (the moment the event happened, which can precede the envelope's created_at by up to the queue-drain interval).

Moderation

case.created

A moderation case (warn, kick, ban, timeout, mute, note) was opened.

Origin: bot, web, api.

json
{
  "case_id": 12345,
  "case_number": 87,
  "type": "warn",
  "user_id": "234567890123456789",
  "moderator_id": "345678901234567890",
  "reason": "Posting referral spam",
  "source": "dashboard"
}

source is one of dashboard, api, bot, sync (cross-server replicator).

case.updated

A case was edited (notes added, expiry changed, reason updated) or its status changed (expired, removed early).

Origin: bot, api.

case.deleted

A case was deleted (soft-delete from the dashboard or a bot-side clear).

Origin: bot, web.

case.appealed

A user submitted an appeal via the public appeal portal.

Origin: web.

json
{
  "case_id": 12345,
  "appeal_id": 9876,
  "user_id": "234567890123456789",
  "message": "I'm really sorry, can you give me another chance…"
}

case.appeal_decided

Staff approved or denied an appeal (needs_info bounces do not fire this).

Origin: web.

json
{
  "appeal_id": 9876,
  "case_id": 12345,
  "user_id": "234567890123456789",
  "status": "approved",
  "reviewer_id": "345678901234567890"
}

Member lifecycle

member.joined

A member joined the guild.

Origin: bot.

json
{
  "user_id": "234567890123456789",
  "username": "alice",
  "account_age_days": 712,
  "is_bot": false,
  "invite_code": "abc123"
}

member.left

A member left or was kicked.

Origin: bot.

member.banned

A member was banned. Fired in addition to case.created when the ban was actioned by Phantom; fired alone for out-of-band native Discord bans.

Origin: bot.

member.unbanned

A ban was lifted.

Origin: bot.

Tickets

ticket.opened

A new ticket was opened.

Origin: bot.

json
{
  "ticket_id": 4242,
  "number": 318,
  "opener_id": "234567890123456789",
  "ticket_type_id": 5,
  "subject": "Refund request",
  "channel_id": "456…"
}

ticket.message

A new message was added to a ticket (either by the opener or by staff).

Origin: bot, api.

ticket.claimed

A staff member claimed a ticket.

Origin: bot.

ticket.closed

A ticket was closed.

Origin: bot, api. (Dashboard-initiated closes are not yet emitted.)

json
{
  "ticket_id": 4242,
  "closed_by_id": "345678901234567890",
  "close_reason": "Refund processed via Stripe",
  "close_source": "staff_command",
  "duration_seconds": 1843
}

ticket.reopened

A closed ticket was reopened.

Origin: bot.

Levelling

xp.level_up

A member crossed a level boundary.

Origin: bot, api.

json
{
  "user_id": "234567890123456789",
  "old_level": 9,
  "new_level": 10,
  "total_xp": 6850
}

Economy

economy.balance_changed

A wallet balance changed. Fires for message earnings, daily claims, transfers, and admin/API adjustments.

Origin: bot, api.

json
{
  "user_id": "234567890123456789",
  "delta": 500,
  "balance": 12300,
  "reason": "Tournament prize",
  "source": "api"
}

source: message_earn | daily | transfer | admin | api. (voice_earn and casino are reserved — those deltas do not emit yet.)

Engagement

giveaway.created

A giveaway was created with /pgiveaway create.

Origin: bot. (Dashboard-created giveaways are not yet emitted.)

giveaway.ended

A giveaway ended and winners were drawn. Fires however the end was triggered (timer, /pgiveaway end, dashboard, API) — the bot draws the winners in every case.

Origin: bot.

json
{
  "giveaway_id": 1234,
  "winner_ids": ["234…", "345…", "456…"],
  "entry_count": 482
}

giveaway.rerolled

A giveaway was rerolled (winners re-drawn).

Origin: bot, web, api.

Security

security.raid_detected

The anti-raid module flagged a coordinated join event.

Origin: bot.

json
{
  "raid_id": 88,
  "joins_in_window": 23,
  "window_seconds": 30,
  "action_taken": "quarantine"
}

security.scam_detected

The anti-scam vision scan flagged a message as a phishing image.

Origin: bot.

json
{
  "user_id": "234567890123456789",
  "channel_id": "456…",
  "message_id": "789…",
  "category": "nitro",
  "confidence": "high",
  "action_taken": "delete_and_timeout"
}

security.nuke_detected

The anti-nuke module flagged a mass-destruction event.

Origin: bot.

json
{
  "actor_id": "234567890123456789",
  "rule_kind": "channel_delete",
  "count_in_window": 6,
  "window_seconds": 30,
  "action_taken": "strip_roles"
}

security.audit_entry

A security audit entry was recorded (permission changes, settings changes, security-sensitive admin actions). High volume on busy servers — subscribe a dedicated endpoint if you consume this.

Origin: bot.

network.hit

A Phantom Network hit fired against a member who joined or is already in your guild.

Origin: bot.

json
{
  "user_id": "234567890123456789",
  "trust_score": 12,
  "approved_report_count": 7,
  "top_category": "scams",
  "top_severity": "high",
  "summary": "Repeated nitro scam DMs across 5 servers."
}

Automod

automod.triggered

An automod rule matched a message (or a join-gate rule matched a new member — channel_id/message_id are null in that case).

Origin: bot.

json
{
  "rule_id": 18,
  "category": "links",
  "user_id": "234567890123456789",
  "channel_id": "456…",
  "message_id": "789…",
  "action_taken": "delete_and_warn"
}

Community

starboard.posted

A message crossed the starboard threshold and was reposted to the starboard channel.

Origin: bot.

json
{
  "source_message_id": "789…",
  "source_channel_id": "456…",
  "author_id": "234567890123456789",
  "star_count": 5,
  "posted_message_id": "890…",
  "posted_channel_id": "567…"
}

Modmail

modmail.thread.opened

A member opened a new modmail thread by DMing the bot.

Origin: bot.

json
{
  "thread_id": 314,
  "user_id": "234567890123456789",
  "channel_id": "456…"
}

modmail.thread.closed

A modmail thread was closed (staff command, dashboard, or auto-close sweep — all routes converge on the same close path).

Origin: bot.

json
{
  "thread_id": 314,
  "user_id": "234567890123456789",
  "closed_by_id": "345678901234567890",
  "close_reason": "Resolved"
}

Testing

test.ping

Fired by the Send test event button on the dashboard. Useful for confirming your receiver is wired up before any real event happens.

Origin: web.

json
{
  "message": "Test event from the Phantom dashboard.",
  "sent_by_user_id": "345678901234567890",
  "sent_at": "2026-05-24T11:32:18+00:00"
}

Phantom is a product of Hydra Labs. The bot is run as a managed service; you do not need to host it yourself.