# Badges

> The server's own badges: earned by a rule over anything Keystone counts, held while in a group, given by a command or read from your own source, shown in chat and the tab list. New in 0.3, off by default.

Source: https://stygion.eu/docs/keystone/badges
Updated: 2026-10-25

New in 0.3, module `badges`, off by default. A server writes its own badges; nothing here depends on STYGION's badges, which are just one possible source.

## Writing a badge (`badges.badges`)

One line per badge, parts separated by ` | `:

```
id=builder | name=Builder | icon=⚒ | colour=#ffca36 | description=24 hours played | rule=played>=24h
```

`rule` says how it is held; several are joined with `&`:

| Rule | Held |
|---|---|
| `manual` | given with `/keystone badge give` |
| `group:<id>` | while the player is in the group |
| `tag:<entity tag>` | while they wear the tag (a quest or datapack reward) |
| `<stat>>=<amount>` | once a counter Keystone keeps reaches it: `played`, `active`, `walked`, `mined`, `mined:<block>`, `killed:<mob>`, `placed`, `deaths` …, times as `24h` |
| `source` | while `source.url` says so |

`hidden=true` keeps a badge out of `{badges}`. Rules are checked for who is online every `check-every` (1 minute). A badge earned by a counter stays; one held by a group, a tag or the source goes when that does.

## Showing them

- `{badges}` in chat and tab-list formats prints the newest icons (`shown`, default 3).
- `/badges [player]` lists them (`keystone.badges`, everybody by default).
- `announce` (on) tells everybody when somebody earns one.
- With the client half: a notice when one is earned, and the HUD value `badges`.

## Your own source

`source.url`: an https address answering with a player's badge ids as a JSON list (or `{"badges": [...]}`); `{uuid}` and `{name}` are filled in, `source.key` goes as a Bearer token. Asked at join and every 10 minutes. Empty: nothing is asked and nothing leaves the server.

## Staff and API

`/keystone badge give|take <player> <badge>` (`keystone.badges.give`). `GET /v1/badges` (scope `players.read`) and `POST /v1/badges/give` (`perks.write`). Addons hear `BadgeChanged`.
