Skip to content

Entities

Entities are the nouns of the world — players, characters, NPCs, groups, locations, maps, and items — every one a ### heading block in nerthus.entities.md. This page covers reading, searching, creating, editing, renaming, and retiring them. Names are URL-encoded in the path; the examples use the canonical session: the character Eraster (owned by the Gracz Stefan), Lord Tussal, and the NPC Opat Perrin.

Reads need entity.read, writes need entity.write. Every example runs against a live daemon — see how the reference is tested.

Routes

Method Path Cmdlet Cap Write
GET /entities Find-NerthusEntity entity.read
GET /entities/integrity Test-NerthusEntityIntegrity entity.read
GET /entities/{name} Get-NerthusEntity entity.read
GET /entities/{name}/player — (owning Gracz of a Postać) entity.read
GET /entities/{name}/history Get-NerthusEntityHistory log.read
GET /entities/{name}/sessions Get-NerthusEntitySessionProfile session.read
GET /entities/{name}/path Get-NerthusEntityPath entity.read
POST /entities New-NerthusEntity entity.write
PATCH /entities/{name} Set-NerthusEntity entity.write
DELETE /entities/{name} Remove-NerthusEntity entity.write
POST /entities/{name}/name Set-NerthusEntityName entity.write

Cap is the required capability ( = public, no token); Write () marks routes that pass the write gate; a in Cmdlet is reached directly, no wrapper. Paths are relative to /v1/api; the cross-cutting contract — middleware, envelopes, status codes — is on the API reference index.

POST /entities/{name}/name (body { name }) renames the block heading: it keeps the old name as an @alias, retargets exact @należy_do references, and answers 409 when the new name is already taken.

List and search entities

GET /v1/api/entities returns the { count, items } envelope. Filter with ?type=, ?status=, ?group=, ?location=, ?name= (substring). Here, the two characters.

GET /v1/api/entities?type=Postać
Authorization: Bearer <token>
await fetch("https://evocation.nerthus.pl/v1/api/entities?type=Postać", {
  headers: { "Authorization": `Bearer ${token}` },
}).then((r) => r.json());

Response 200 (trimmed):

{ "count": 2, "items": [
  { "Name": "Lord Tussal", "Type": "Postać", "Owner": "Roman" },
  { "Name": "Eraster", "Type": "Postać", "Owner": "Stefan" }
] }

Fetch one entity

GET /v1/api/entities/{name} resolves the name and returns the full projection.

GET /v1/api/entities/Eraster
Authorization: Bearer <token>
await fetch("https://evocation.nerthus.pl/v1/api/entities/Eraster", {
  headers: { "Authorization": `Bearer ${token}` },
}).then((r) => r.json());

Response 200 (trimmed):

{ "Name": "Eraster", "Type": "Postać", "Owner": "Stefan", "PuSuma": "60", "Status": "Aktywny" }

The owning player of a character

GET /v1/api/entities/{name}/player returns the Gracz who owns a Postać.

GET /v1/api/entities/Eraster/player
Authorization: Bearer <token>
await fetch("https://evocation.nerthus.pl/v1/api/entities/Eraster/player", {
  headers: { "Authorization": `Bearer ${token}` },
}).then((r) => r.json());

Response 200 (trimmed):

{ "Name": "Stefan", "Type": "Gracz", "MargonemId": "100001" }

Sessions an entity took part in

GET /v1/api/entities/{name}/sessions scans parsed metadata (@PU, @Uczestnicy, locations) for the entity — needs session.read.

GET /v1/api/entities/Eraster/sessions
Authorization: Bearer <token>
await fetch("https://evocation.nerthus.pl/v1/api/entities/Eraster/sessions", {
  headers: { "Authorization": `Bearer ${token}` },
}).then((r) => r.json());

Response 200:

{ "entity": "Eraster", "count": 1, "sessions": [{ "header": "2026-07-01, Eraster rozmawia z Tussalem, Anward", "date": "2026-07-01" }] }

The audit history of an entity

GET /v1/api/entities/{name}/history returns audit lines touching the entity — needs log.read.

GET /v1/api/entities/Eraster/history
Authorization: Bearer <token>
await fetch("https://evocation.nerthus.pl/v1/api/entities/Eraster/history", {
  headers: { "Authorization": `Bearer ${token}` },
}).then((r) => r.json());

Response 200:

{ "entity": "Eraster", "count": 0, "items": [] }

Integrity check

GET /v1/api/entities/integrity reports schema findings across all entity blocks.

GET /v1/api/entities/integrity
Authorization: Bearer <token>
await fetch("https://evocation.nerthus.pl/v1/api/entities/integrity", {
  headers: { "Authorization": `Bearer ${token}` },
}).then((r) => r.json());

Response 200:

{ "count": 0, "items": [] }

Preview a create without writing

?dryRun=true returns 200 { wouldCreate } and touches no disk — proven by the follow-up 404. The scratch entity is a servant in Tussal's residence.

POST /v1/api/entities?dryRun=true
Content-Type: application/json
Authorization: Bearer <token>

{ "name": "Sługa Tussala", "type": "NPC" }
await fetch("https://evocation.nerthus.pl/v1/api/entities?dryRun=true", {
  method: "POST",
  headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}` },
  body: JSON.stringify({ name: "Sługa Tussala", type: "NPC" }),
});

Response 200:

{ "wouldCreate": "Sługa Tussala", "type": "NPC" }

Create an entity

POST /v1/api/entities with a (name, type) — the pair must be unique. Type must be one of the seven in the schema.

POST /v1/api/entities
Content-Type: application/json
Authorization: Bearer <token>

{ "name": "Sługa Tussala", "type": "NPC" }
await fetch("https://evocation.nerthus.pl/v1/api/entities", {
  method: "POST",
  headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}` },
  body: JSON.stringify({ name: "Sługa Tussala", type: "NPC" }),
});

Response 201:

{ "created": "Sługa Tussala", "type": "NPC" }

Rejected: duplicate

The same (name, type) twice is 409 — a duplicate heading would shadow the first.

POST /v1/api/entities
Content-Type: application/json
Authorization: Bearer <token>

{ "name": "Sługa Tussala", "type": "NPC" }
await fetch("https://evocation.nerthus.pl/v1/api/entities", {
  method: "POST",
  headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}` },
  body: JSON.stringify({ name: "Sługa Tussala", type: "NPC" }),
});

Response 409:

{ "error": "a 'NPC' named 'Sługa Tussala' already exists — duplicate headings shadow each other; qualify the name (e.g. 'Sługa Tussala (Miasto)')" }

Fetch the created entity

GET /v1/api/entities/S%C5%82uga%20Tussala
Authorization: Bearer <token>
await fetch("https://evocation.nerthus.pl/v1/api/entities/S%C5%82uga%20Tussala", {
  headers: { "Authorization": `Bearer ${token}` },
}).then((r) => r.json());

Response 200 (trimmed):

{ "Name": "Sługa Tussala", "Type": "NPC", "Status": "Aktywny" }

Update a tag

PATCH /v1/api/entities/{name} sets one tag from the closed schema. Legacy ASCII spellings canonicalize; an unknown tag is 422.

PATCH /v1/api/entities/S%C5%82uga%20Tussala
Content-Type: application/json
Authorization: Bearer <token>

{ "tag": "lokacja", "value": "Thuzal" }
await fetch("https://evocation.nerthus.pl/v1/api/entities/S%C5%82uga%20Tussala", {
  method: "PATCH",
  headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}` },
  body: JSON.stringify({ tag: "lokacja", value: "Thuzal" }),
});

Response 200:

{ "updated": "Sługa Tussala", "tag": "lokacja", "changed": true }

Rejected: unknown type

A type outside the closed schema is 422, nothing written. Here a real entity name with a deliberately invalid type.

POST /v1/api/entities
Content-Type: application/json
Authorization: Bearer <token>

{ "name": "Rezydencja Tussal", "type": "Smok" }
await fetch("https://evocation.nerthus.pl/v1/api/entities", {
  method: "POST",
  headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}` },
  body: JSON.stringify({ name: "Rezydencja Tussal", type: "Smok" }),
});

Response 422:

{ "error": "Unknown type: Smok" }

Rename an entity

POST /v1/api/entities/{name}/name renames the heading, keeps the old name as @alias, and retargets @należy_do references.

POST /v1/api/entities/S%C5%82uga%20Tussala/name
Content-Type: application/json
Authorization: Bearer <token>

{ "name": "Sługa Lorda Tussala" }
await fetch("https://evocation.nerthus.pl/v1/api/entities/S%C5%82uga%20Tussala/name", {
  method: "POST",
  headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}` },
  body: JSON.stringify({ name: "Sługa Lorda Tussala" }),
});

Response 200:

{ "renamed": "Sługa Tussala", "to": "Sługa Lorda Tussala" }

Retire an entity (soft delete)

DELETE /v1/api/entities/{name} marks the block @status: Usunięty — never physical removal.

DELETE /v1/api/entities/S%C5%82uga%20Lorda%20Tussala
Authorization: Bearer <token>
await fetch("https://evocation.nerthus.pl/v1/api/entities/S%C5%82uga%20Lorda%20Tussala", {
  method: "DELETE",
  headers: { "Authorization": `Bearer ${token}` },
});

Response 200:

{ "softDeleted": "Sługa Lorda Tussala", "status": "Usunięty" }