# Rozhraní — úplný seznam

> Všech 44 cest lokálního API: co potřebují za scope, co berou, co vrací — a jak si na to napojit vlastní nástroj, z téhle mašiny i zvenčí.

Source: https://stygion.eu/cs/docs/keystone/api-reference
Updated: 2026-09-07

Tenhle seznam **není psaný z hlavy**. Mod si dokument o sobě generuje ze svých vlastních rout (`GET /v1/openapi.json`), takže se nemůže mýlit v tom, co existuje — a tahle stránka je z něj vytažená příkazem `scripts/reference.sh` v repozitáři modu. Když si nejsi jistý, ptej se svého serveru, ne téhle stránky.

Platí pro **0.1.1**. Cest je **44**.

---

## Než něco zavoláš

### 1. Vyrob si klíč

```
/keystone key new muj-nastroj status.read players.read
```

Klíč se vypíše **jednou** a nikdy víc. Dej mu tu nejužší sadu scopů, která odvede práci: skript, co hlídá, jestli server běží, chce `status.read` a nic dalšího.

### 2. Zavolej

```bash
curl -sS -H "Authorization: Bearer ks_…" \
  http://127.0.0.1:25586/v1/status
```

`GET` bere parametry v adrese, `POST` je posílá jako formulář:

```bash
curl -sS -X POST -H "Authorization: Bearer ks_…" \
  -d "player=Honza" -d "group=vip" -d "for=30d" \
  -d "note=koupeno na webu" \
  http://127.0.0.1:25586/v1/players/group
```

### 3. Co znamenají odpovědi

| Kód | Co to je |
|---|---|
| `200` | Vyšlo to. |
| `400` | Něco v požadavku nesedělo, a odpověď říká co. |
| `403` | Klíč je pravý, ale nemá scope, který ta cesta chce. |
| `404` | Taková cesta není — **nebo nemáš klíč vůbec**. Odpovídá se stejně schválně: volající bez klíče se o tomhle serveru nedozví nic. |
| `429` | Překročil jsi, co ten klíč smí za minutu. |

---

## Kudy se k tomu dostaneš

### Jen z téhle mašiny (výchozí, a je to ta bezpečná volba)

```toml
[api]
enabled = true
address = "127.0.0.1"
port = 25586
```

Nic není vidět zvenčí. Panel i tvoje skripty běží na tom samém stroji.

### Z tvého počítače, přes tunel (doporučené u hostovaného serveru)

Nechej mod na loopbacku a přines si port k sobě:

```bash
ssh -L 25586:127.0.0.1:25586 ty@tvuj-server
curl -sS -H "Authorization: Bearer ks_…" http://127.0.0.1:25586/v1/status
```

**Nic se nevystavuje** a `/keystone panel` se otevře u tebe v prohlížeči.

### Z domácí sítě

```
/keystone set keystone.api.address 0.0.0.0
/keystone set keystone.api.reachable-at 192.168.1.100
```

První říká, kde se **poslouchá**, druhé, jakou adresu si má mod napsat do odkazu na editor a do `openapi.json` — `0.0.0.0` je dobrá odpověď na to první a nepoužitelná na to druhé. K tomu pusť port jen z LAN, ne ze světa:

```bash
sudo ufw allow from 192.168.1.0/24 to any port 25586 proto tcp
```

### Zvenčí, přes reverzní proxy nebo tunel

Nech mod na loopbacku a postav před něj něco, co umí TLS:

```nginx
location /keystone/ {
    proxy_pass http://127.0.0.1:25586/;
    proxy_set_header Host $host;
}
```

```
/keystone set keystone.api.reachable-at keystone.tvujserver.eu
```

**Nikdy nedávej `api.address` na veřejnou adresu bez TLS.** Klíč jde v hlavičce a přes `http://` po internetu ho přečte kdokoliv po cestě. A API umí všechno, co umí mod.

---

## Živý proud

```bash
curl -N -H "Authorization: Bearer ks_…" \
  http://127.0.0.1:25586/v1/events
```

Drží spojení otevřené a píše do něj události, jak se dějí (`text/event-stream`). Tři řádky v prohlížeči:

```js
const events = new EventSource('/v1/events');
events.onmessage = (e) => console.log(JSON.parse(e.data));
```

Ověřuje se jako všechno ostatní a bez klíče odpoví `404`.

---

## Stav a měření

| Metoda | Cesta | Scope | K čemu |
|---|---|---|---|
| `GET` | `/v1/status` | `status.read` | Co tenhle server je a jak mu je |
| `GET` | `/v1/metrics` | `status.read` | Co dělá právě teď a poslední čtvrthodina |
| `GET` | `/v1/metrics/history` | `status.read` | Po minutách, tak daleko dozadu, jak to nastavení drží |
| `GET` | `/v1/entities` | `status.read` | Co je načtené ve světě a co by úklid teď sebral |
| `GET` | `/v1/gate` | `status.read` | Jestli je server otevřený a kolik míst se drží stranou |
| `GET` | `/v1/catalog` | `status.read` | Všechno, co tenhle pack načetl: registry, obsah jednoho (`?of=minecraft:item`, s `from`/`limit`/`like`), nebo jeho tagy (`&tags=true`) |
| `GET` | `/v1/bench` | `server.read` | Zátěžové běhy, které tenhle server udělal (`?id=` pro jeden celý) |
| `GET` | `/v1/openapi.json` | `status.read` | Tenhle dokument |

```bash
curl -sS -H "Authorization: Bearer ks_…" \
  "http://127.0.0.1:25586/v1/catalog?of=minecraft:item&like=diamond&limit=20"
```

## Lidi a oprávnění

| Metoda | Cesta | Scope | K čemu |
|---|---|---|---|
| `GET` | `/v1/players` | `players.read` | Kdo je právě online |
| `GET` | `/v1/progress` | `players.read` | Co jeden hráč udělal, nebo žebříček jednoho počítadla |
| `GET` | `/v1/skins` | `players.read` | Co má kdo na sobě a odkud to je |
| `GET` | `/v1/accounts` | `players.read` | Kolik účtů má heslo a kdo čeká, až se prokáže |
| `GET` | `/v1/bans` | `players.read` | Každý ban, který ještě stojí |
| `GET` | `/v1/tickets` | `players.read` | Tickety (`?id=` pro jeden se vším, co se v něm řeklo, `?player=`) |
| `GET` | `/v1/votes` | `players.read` | Hlasy, které serveru přišly, a jak je na tom party cíl (`?player=`, `?limit=`) |
| `GET` | `/v1/discord/links` | `players.read` | Které herní účty má jeden Discord uživatel propojené (`?discord=<id>`) |
| `GET` | `/v1/groups` | `permissions.read` | Každá skupina oprávnění, nejtěžší první |
| `POST` | `/v1/players/check` | `permissions.read` | Jestli někdo něco smí — a které pravidlo o tom rozhodlo |
| `POST` | `/v1/players/group` | `permissions.write` | Dej někoho do skupiny, nebo mu v ní prodluž čas |
| `POST` | `/v1/players/perk` | `perks.write` | Dej někomu pojmenovanou výhodu, případně do data |
| `POST` | `/v1/players/grants` | `perks.read` | Co jeden hráč drží, odkud to má a kdy to končí |

**Parametry:**

| Cesta | Bere |
|---|---|
| `/v1/players/check` | `player` — jméno někoho online · `permission` — na které oprávnění se ptáš |
| `/v1/players/grants` | `player` — jméno někoho online |
| `/v1/players/group` | `player` · `group` — id skupiny · `for` — `30d`, `12h`, `90m`, nebo vynech pro napořád · `note` — proč, pro toho, kdo to bude číst později |
| `/v1/players/perk` | `player` · `perk` — co dostane · `for` · `note` |

### Jak z toho udělat obchod

Na serveru, který není v online režimu, **jméno napsané do formuláře nedokazuje nic**. Pořadí je tohle:

```bash
# 1. Kdo je ten člověk ve hře — podle Discordu, kterým se přihlásil na webu
curl -sS -H "Authorization: Bearer ks_…" \
  "http://127.0.0.1:25586/v1/discord/links?discord=123456789012345678"

# 2. Doruč mu, co si koupil, s datem konce
curl -sS -X POST -H "Authorization: Bearer ks_…" \
  -d "player=Honza" -d "group=vip" -d "for=30d" -d "note=objednávka 4821" \
  http://127.0.0.1:25586/v1/players/group
```

Hodnost skončí sama v ten den. Nikdo si nemusí pamatovat, že ji má sundat.

## Provoz

| Metoda | Cesta | Scope | K čemu |
|---|---|---|---|
| `GET` | `/v1/operations` | `operations.read` | Co je naplánované a kolik zbývá |
| `GET` | `/v1/operations/history` | `operations.read` | Co v poslední době proběhlo, nejnovější první |
| `POST` | `/v1/operations/run` | `operations.run` | Spusť jednu teď, nebo se zpožděním, s obvyklými varováními |
| `POST` | `/v1/operations/cancel` | `operations.run` | Odvolej, co je rozjeté, a vrať se k rozvrhu |
| `POST` | `/v1/gate/maintenance` | `operations.run` | Zavři server na údržbu, nebo ho zase otevři |
| `GET` | `/v1/backups` | `backup.read` | Každá záloha, nejnovější první, i s tím, co stojí na disku |
| `POST` | `/v1/backups/restore` | `backup.restore` | Vrať zálohu — připraví se a udělá při příštím startu |

**Parametry:**

| Cesta | Bere |
|---|---|
| `/v1/operations/run` | `operation` — která · `in` — za kolik vteřin, `0` hned |
| `/v1/operations/cancel` | `operation` — která |
| `/v1/gate/maintenance` | `closed` — `true` zavřít, `false` otevřít · `reason` — co se děje, uvidí to každý, kdo se pokusí připojit · `until` — kdy to má skončit, tvými slovy |
| `/v1/backups/restore` | `backup` — jméno zálohy, nebo `cancel` pro odvolání |

## Nastavení a záznam

| Metoda | Cesta | Scope | K čemu |
|---|---|---|---|
| `GET` | `/v1/settings` | `settings.read` | Každé nastavení, co který modul deklaroval, co to je a co v tom stojí |
| `POST` | `/v1/settings` | `settings.write` | Změň jedno. Odmítne se i s důvodem, když hodnota neodpovídá tomu, co ta věc je |
| `GET` | `/v1/settings/history` | `settings.read` | Každá změna, nejnovější první, i s tím, jaká byla hodnota předtím |
| `POST` | `/v1/settings/rollback` | `settings.write` | Vrať, co jedna verze změnila. Vrácení je samo verze, takže jde vrátit taky |
| `POST` | `/v1/reload` | `settings.write` | Přečti znovu všechny soubory s nastavením. Nic se nerestartuje a nikoho to nevyhodí |
| `GET` | `/v1/audit` | `audit.read` | Kdo co přes tohle rozhraní změnil, nejnovější první. Čtení se nezapisuje, změny a odmítnutí ano |
| `GET` | `/v1/keys` | `keys.read` | Klíče, které tenhle server vydal, bez jejich tajemství |

**Parametry:** `/v1/settings` bere `setting` (celé jméno, třeba `operations.restart.when`) a `value`; `/v1/settings/rollback` bere `version`.

```bash
curl -sS -X POST -H "Authorization: Bearer ks_…" \
  -d "setting=operations.restart.when" -d "value=every 6h" \
  http://127.0.0.1:25586/v1/settings
```

Co všechno jde nastavit, je na stránce [Všechna nastavení](/docs/keystone/settings-reference).

## Konzole, chat a Discord

| Metoda | Cesta | Scope | K čemu |
|---|---|---|---|
| `GET` | `/v1/console` | `console.read` | Poslední řádky, co server vypsal, nejstarší první. Drží se v paměti, ne v databázi |
| `GET` | `/v1/chat` | `chat.read` | Poslední, co padlo v chatu, nejstarší první |
| `GET` | `/v1/events` | `events.read` | Živý proud událostí |
| `GET` | `/v1/discord` | `server.read` | Jestli je most na Discord připojený a jak moc je pozadu |

## Asistent

| Metoda | Cesta | Scope | K čemu |
|---|---|---|---|
| `POST` | `/v1/assistant/ask` | `assistant.write` | Zeptej se ho. Odpověď přijde tímhle voláním |
| `POST` | `/v1/assistant/incident` | `assistant.write` | Podej mu poslední úsek konzole a chatu a zeptej se, co vypadá špatně |
| `POST` | `/v1/assistant/decide` | `assistant.write` | Souhlas s navrženou změnou, nebo ji nech být |
| `GET` | `/v1/assistant/proposals` | `assistant.read` | Změny, které chce udělat a nikdo o nich zatím nerozhodl |
| `GET` | `/v1/assistant/threads` | `assistant.read` | Konverzace, které byly, nejnovější první |
| `GET` | `/v1/assistant/thread` | `assistant.read` | Jedna konverzace, nejstarší zpráva první |

**Parametry:** `/v1/assistant/ask` bere `question`; `/v1/assistant/decide` bere `proposal` (která) a `answer` (`yes` nebo `no`).

---

## Addony na JVM

Když stavíš addon v Javě, přes HTTP nemluvíš. Kompiluješ proti `keystone-api`, který jede uvnitř toho samého jaru (`META-INF/jarjar/eu.stygion.keystone.api-<verze>.jar`) a **nemá žádné vlastní závislosti**, ani logovací. Registruje se přes něj vlastní modul, příkaz, oprávnění, zdroj hodností — a taky **vlastní route**, která pak vypadá v tomhle seznamu a v `openapi.json` úplně stejně jako ty naše.

---

## Co se zapisuje

Každá změna přes rozhraní je auditní řádek: který klíč, co, kdy — a **každé odmítnutí taky**. Klíč, který opakovaně zkouší, co nesmí, je jediná stopa, kterou o převzaté integraci dostaneš. Citlivé příkazy se maskují z auditu, konzole i logu.
