Hooks

Hook events are pushed to client mods over the plugin channel and to backend apps over webhooks. Every event is gated by a backing read scope, and grouped here by who can see it.

Event envelope

Webhooks receive every hook event in this envelope. Only data changes per event type.

{
  "id": "evt_01J...",
  "type": "player.enchant_proc",
  "version": 1,
  "createdAt": "2026-06-04T00:00:00.000Z",
  "serverScope": "aether",
  "producer": { "kind": "minecraft_server", "id": "aether" },
  "actor": { "playerId": "00000000-0000-0000-0000-000000000000" },
  "subject": { "playerId": "00000000-0000-0000-0000-000000000000" },
  "visibility": "self",
  "requiredScopes": ["hooks.player.enchant_proc:read"],
  "data": { /* event-specific fields */ }
}
idstring

Globally unique, stable id. Delivery is at least once, so dedupe on this.


typestring

The event type from the catalog below, e.g. player.enchant_proc.


versionnumber

Payload contract version. Branch on it when a payload shape changes.


createdAtISO 8601

When the event occurred.


serverScopestring

Which server it happened on, e.g. aether or celestial.


producerobject

What emitted the event, as { kind, id }.


actorobject

Who caused it, with a playerId when a player is known.


subjectobject

Who or what the event is about — a player, gang, or the server.


visibilitystring

self, gang, server, or app owner — who is allowed to receive it.


requiredScopesstring[]

The scopes that gate this event.


dataobject

Event-specific payload. Some events pass runtime data through unchanged — read it defensively.

On the plugin channel, the event arrives inside an event message. The same fields webhooks get in data sit at payload.payload. When that data is mock, the message also carries testingData: true.

{
  "type": "event",
  "event": "hook",
  "sessionId": "sess_01J...",
  "eventType": "player.enchant_proc",
  "payload": {
    "id": "evt_1042",
    "type": "player.enchant_proc",
    "eventType": "player.enchant_proc",
    "version": 1,
    "subjectType": "player",
    "serverScope": "aether",
    "occurredAt": "2026-06-04T00:00:00.000Z",
    "playerId": "00000000-0000-0000-0000-000000000000",
    "playerName": "Steve",
    "payload": { /* the same fields webhooks get in data */ }
  }
}
Delivery on the plugin channel

Hook events have their own packet budget per player, apart from HUD, overlay and marker traffic.

Today the budget refills 20 tokens a second and holds up to 40. A packet costs one token plus one per KiB.

A packet over budget is dropped, not queued or sent again. The game counts drops on your session as droppedMessages, which GET /v1/cosmic-api/runtime/servers/:serverScope/mod-sessions/self returns with mod.sessions.same_mod:read.

After a gap, read the matching endpoint to catch up. Webhooks do not share this budget.

Your player

Events about your own player, delivered only to the player who granted access.

Payload
enchantIdstring

The enchant id, e.g. powerball.


displayNamestring

Name and level as the game shows them, color codes included.


levelnumber

The enchant level.


sourcestring

What set it off: mining, combat or manual. manual is a Powerball launched by a click. Some procs add a detail after a colon, such as combat:buff or mining:chain, so match the part before it.


cooldownRemainingMsnumber

manual only. The cooldown the launch started, in milliseconds.


causestring

Procs from an attack only. The damage cause, e.g. ENTITY_ATTACK.


targetId / targetTypestring

The entity you hit, when known. targetType is the entity type, e.g. PLAYER.


ticknumber

The server tick of the proc.

Example
{
  "enchantId": "powerball",
  "displayName": "&9Powerball §b§lIII",
  "level": 3,
  "source": "manual",
  "cooldownRemainingMs": 45000,
  "tick": 1843021
}

Cooldowns changed
player.cooldowns.changed

Fires when your cooldowns change.

player.cooldowns:read
Client
Webhook

Effects changed
player.effects.changed

Fires when your active effects change.

player.effects:read
Client
Webhook

Absorber used
player.absorber.used

Fires when your absorber is used.

hooks.player.absorber:read
Client
Webhook

Command succeeded
player.command.succeeded

Fires when one of your approved commands runs.

hooks.player.command:read
Client
Webhook

Pet changed
player.pet.changed

Fires when your active pet changes.

player.pets:read
Client
Webhook

Trinket changed
player.trinket.changed

Fires when your trinkets change.

player.trinkets:read
Client
Webhook

Payload
channelstring

global, gang, truce or ad.


previousChannelstring | null

The channel before. null on the session event.


gangId / gangTitlestring

Your gang, or empty strings when you have none.


reasonstring

command, truce_ended, normalized, or session when your session resolves.

The session event means a mod that connects mid-game learns the current channel without waiting for a change.

Example
{
  "previousChannel": null,
  "channel": "gang",
  "gangId": "00000000-0000-0000-0000-000000000002",
  "gangTitle": "Wolves",
  "reason": "session"
}

Bandit killed
bandit.killed

Fires when you kill a bandit.

hooks.bandit.kill:read
Client
Webhook

Library changed
player.library.changed

Fires when your library, or a library shared with you, gains or loses items.

player.library:read
Client
Webhook
Relationship bypass for webhooks

Library access changed
player.library.access.changed

Fires when a library share you own or receive is added, changed or removed.

player.library:read
Client
Webhook
Relationship bypass for webhooks

Vault contribution changed
player.vault.contribution.changed

Fires about once a second while your damage or rank in a mine vault raid changes, while you are in the top 25.

events:read
Client
Webhook

Emblem changed
player.emblem.changed

Fires when your equipped emblem, its tier or your buffs toggle changes.

player.emblems:read
Client
Webhook

Emblem progress changed
player.emblem.progress.changed

Fires at most every five seconds while your emblem progress changes.

player.emblems:read
Client
Webhook

Emblem unlocked
player.emblem.unlocked

Fires when you unlock an emblem tier.

player.emblems:read
Client
Webhook

Top credits changed
player.top_credits.changed

Fires when your Top Credit balance changes.

player.top_credits:read
Client
Webhook

Payload
bagIdstring

The backpack's id.


slotnumber

The inventory slot it sits in.


level / capacitynumber

Backpack level and how many satchels it holds.


usedSlotsnumber

Satchels stored now.


energy / maxEnergynumber

The backpack's energy.


revisionnumber

Goes up with each change to the bag.


storedSatchelsobject[]

Every satchel inside, in the satchel row shape, with slot as the place in the bag.

There is no need to read the satchels endpoint again. A busy bag sends its latest state at most once a second.

Example
{
  "bagId": "00000000-0000-0000-0000-000000000001",
  "slot": 8,
  "level": 2,
  "usedSlots": 1,
  "capacity": 10,
  "energy": 120,
  "maxEnergy": 300,
  "revision": 57,
  "storedSatchels": [
    { "slot": 0, "type": "iron_ore_satchel", "material": "IRON_ORE", "name": "Iron Ore Satchel", "amount": 1, "level": 1,
      "energy": 40, "maxEnergy": 100, "ore": "IRON", "refined": false, "tier": "regular", "count": 300, "capacity": 1000 }
  ]
}

Custom set changed
player.custom_set.changed

Fires when you complete or break a Death or Greed set.

player.custom_sets:read
Client
Webhook

Payday changed
player.payday.changed

Fires when your Greed set payday starts or ends.

player.custom_sets:read
Client
Webhook

Death mark changed
player.death_mark.changed

Fires when a death mark is placed on you, cleared or expires.

player.custom_sets:read
Client
Webhook

Ground Zero points changed
player.ground_zero.points.changed

Fires about once a second while your Ground Zero points change.

player.ground_zero:read
Client
Webhook

Payload
enchantIdstring

The armor enchant that answered your hit, or valor_mask_dodge when a Valor Mask dodged it.


displayNamestring

Name and level as the game shows them.


levelnumber

The enchant level.


sourcestring

Always combat.


causestring | null

The damage cause of your hit, e.g. ENTITY_ATTACK or PROJECTILE.


targetIdstring

The player you hit.


targetNamestring

Their name.


targetTypestring

Always PLAYER.


ticknumber

The server tick. Repeats of one enchant on one target in a tick merge into one event.

Example
{
  "enchantId": "maneuver",
  "displayName": "&fManeuver §bII",
  "level": 2,
  "source": "combat",
  "cause": "ENTITY_ATTACK",
  "targetId": "00000000-0000-0000-0000-000000000001",
  "targetName": "Alex",
  "targetType": "PLAYER",
  "tick": 1843090
}

Payload
reasonstring

mining, sell, store or extract.


revisionnumber

Goes up by one per event and starts over when the player rejoins. A gap means you missed one.


changedobject[]

The full row of each touched slot that still holds a satchel, shaped like data.satchels[] on the satchels read.


removedSlotsnumber[]

Touched slots that no longer hold a satchel.

The rows are complete, so apply them as they come. There is no need to read the satchels endpoint again.

Example
{
  "reason": "mining",
  "revision": 418,
  "changed": [
    { "slot": 3, "type": "diamond_ore_satchel", "material": "DIAMOND_ORE", "name": "Diamond Ore Satchel", "amount": 1, "level": 2,
      "energy": 80, "maxEnergy": 200, "ore": "DIAMOND", "refined": false, "tier": "regular", "count": 1250, "capacity": 5000 }
  ],
  "removedSlots": []
}

Payload

Every field of data.wallet on the balances read, plus:

changedstring[]

The fields that moved since the last event.


balanceDeltanumber

How much balance moved since the last event. 0 on the session event.


reasonstring

session on the first event after your session resolves. That event carries every field. Absent otherwise.

The game compares your balances once a second and sends only when one moved. A new balanceRevision alone sends nothing.

Example
{
  "balance": 1262500.5,
  "balanceRevision": 813,
  "seasonalCosmicCoins": 340,
  "itemFlipCredits": 12,
  "giftCred": 5,
  "bloodDiamonds": 18,
  "bloodDiamondsPeriodEndsAt": "2026-10-12T00:00:00Z",
  "changed": ["balance"],
  "balanceDelta": 12500
}

Payload

Every field of data.progression on the progression read, plus:

reasonstring

prestige, level_up, skill_tree or xp. session on the first event after your session resolves. That event carries every field.


experienceDeltanumber

Experience gained since the last event. 0 on the session event.

Example
{
  "level": 64,
  "experience": 18420.5,
  "experienceToNextLevel": 39830,
  "levelCap": 100,
  "prestige": 2,
  "prestigePerks": [ { "id": "level_101", "unlocked": false } ],
  "skillTree": { "availablePoints": 1, "totalPoints": 12, "spentPoints": 11, "freeResetsRemaining": 1,
    "perks": [ { "tree": "prospector", "key": "ore_duplication", "level": 3, "maxLevel": 3 } ] },
  "reason": "xp",
  "experienceDelta": 170
}

Payload

Every field of data.state on the state read except sidebar, plus:

changedstring[]

The fields that moved since the last event. Empty on the session event.


reasonstring

session on the first event after your session resolves. That event carries every field. Absent otherwise.

Energy moves as you mine, so expect about one event a second while mining.

Example
{
  "planet": "aether",
  "world": "prison",
  "dimension": "main",
  "zone": "diamond",
  "regions": ["mine_diamond"],
  "mine": { "region": "mine_diamond", "ore": "diamond" },
  "combatTag": { "active": false, "expiresAt": null },
  "boosters": [],
  "energy": { "current": 12620, "max": 50000, "chargePercent": 25, "pickaxeLevel": 42 },
  "changed": ["energy"]
}

Payload
layoutstring

toggles, pickaxe, or the board an area shows, such as boss or koth.


compactboolean

Whether compact mode is on.


componentsobject[]

Every sidebar line as key, enabled and order.


reasonstring

session on the first event after your session resolves. Absent otherwise.

Line values are not sent. Read them from sidebar.values on the state read, or with the player.state.read action.

Example
{
  "layout": "pickaxe",
  "compact": false,
  "components": [
    { "key": "current_zone", "enabled": true, "order": 0 },
    { "key": "balance", "enabled": false, "order": 1 }
  ]
}
Your gang

Events shared with the members of your current gang.

Gang chat message
gang.chat.message.created

Fires when a message is posted in your gang chat.

gang.messages:read
Client
Webhook
Relationship bypass for webhooks

Gang ping
gang.ping.created

Fires when a gang or truce ping is created.

gang.pings:read
Client
Webhook
Relationship bypass for webhooks
Server-wide

Live world events broadcast for the whole server.

Server event changed
server.event.changed

Fires when the current public server event changes.

events:read
Client
Webhook

Event schedule changed
server.event.schedule.changed

Fires when the server event schedule changes.

events:read
Client
Webhook

Meteor landing changed
server.meteor.landing.changed

Fires when meteor landing information changes.

server.meteors:read
Client
Webhook

Merchant spawned
server.merchant.spawned

Fires when a merchant spawns.

server.merchants:read
Client
Webhook

Merchant despawned
server.merchant.despawned

Fires when a merchant despawns.

server.merchants:read
Client
Webhook

Guards snapshot changed
server.guards.snapshot.changed

Fires when the server's guard counts change. It carries counts only, by design; read single guards from the nearby guards endpoint.

server.guards:read
Client
Webhook
Relationship bypass for webhooks

Weather changed
server.weather.changed

Fires when a weather event starts or ends.

events:read
Client
Webhook

Weather surge changed
server.weather.surge.changed

Fires when a weather surge starts or ends.

events:read
Client
Webhook

Mine vault raid started
server.vault.raid.started

Fires when a mine vault raid begins.

events:read
Client
Webhook

Mine vault raid ended
server.vault.raid.ended

Fires when a mine vault raid ends, with the outcome and top damagers.

events:read
Client
Webhook

Prison Break phase changed
server.prisonbreak.phase.changed

Fires when the Prison Break match moves to a new phase.

events:read
Client
Webhook

Top credit checkpoint paid
server.top_credit.checkpoint.completed

Fires when a Top Credit checkpoint pays out, with the awarded ranks.

player.top_credits:read
Client
Webhook

Ground Zero reset changed
server.ground_zero.reset.changed

Fires when a Ground Zero reset is scheduled, starts, completes or retries.

player.ground_zero:read
Client
Webhook

Payload
punishmentIdstring

The ban's id. Each planet sends its own copy, so dedupe on it.


player{ uuid, name }

The banned player. name is null when the game could not look it up.


typestring

ban or temporary_ban.


reasonstring

The ban reason.


durationMsnumber | null

null for a permanent ban.


issuedAt / expiresAtISO 8601

expiresAt is null for a permanent ban.


staffMemberstring

Who issued it.

These are the fields the public bans page shows, and nothing else. IP bans are not sent.

Example
{
  "punishmentId": "6710a3f2c9e77b2d4f1e8a90",
  "player": { "uuid": "00000000-0000-0000-0000-000000000000", "name": "Steve" },
  "type": "temporary_ban",
  "reason": "Cheating",
  "durationMs": 604800000,
  "issuedAt": "2026-10-11T00:00:00Z",
  "expiresAt": "2026-10-18T00:00:00Z",
  "staffMember": "Landon"
}

Payload
fingerstring

index, thumb, pinky or middle.


aliveboolean

Whether the banker is up.


respawnInSecondsnumber

0 while alive.


respawnAtISO 8601 | null

When it comes back. null while alive.


reasonstring

spawned, defeated or lost.

Banker locations are on the Midas read.

Example
{
  "finger": "index",
  "alive": false,
  "respawnInSeconds": 300,
  "respawnAt": "2026-10-11T00:05:00Z",
  "reason": "defeated"
}

Payload
phase / previousPhasestring

locked, open, ongoing or ending.


openedBy{ uuid, name } | null

Who opened the room. null while locked.


openedAtISO 8601 | null

When it opened.


secondsRemainingnumber | null

Time left in open or ending. null in other phases.


playersInside / maxPlayersnumber

Players in the room and the cap.

Example
{
  "phase": "open",
  "previousPhase": "locked",
  "openedBy": { "uuid": "00000000-0000-0000-0000-000000000001", "name": "Steve" },
  "openedAt": "2026-10-11T00:00:00Z",
  "secondsRemaining": 120,
  "playersInside": 1,
  "maxPlayers": 10
}
App owner

Operational events about your app's sessions, delivered to webhooks.

Session connected
mod.session.connected

Fires when a player connects with your mod.

mod.sessions:read
Webhook

Session disconnected
mod.session.disconnected

Fires when a player disconnects from your mod.

mod.sessions:read
Webhook