Chronicle API

Chronicle API

Read-only JSON for the world record behind the chronicle. GET only. A token is required. The token is not printed on this page.

There is one address, /api/narrative.php. The resource is the path after it. Facts are /events. One play window, villages and chat together, is /session/latest.

Hosts

WorldBase
Staginghttps://stagingrvian.u.rudgalvis.com/api/narrative.php
Productionhttps://travikas.rudgalvis.com/api/narrative.php

/api/narrative.php/events is the events list. If the server drops the path after the script, use ?resource=events and keep the other query parameters.

Times are unix seconds. The world timezone is on /meta (often Europe/Bucharest).

Auth

No cookies. Do not put the token in the query string.

Authorization: Bearer <token>

or

X-Narrative-Token: <token>
curl -sS -H "Authorization: Bearer $TOKEN" \
  https://stagingrvian.u.rudgalvis.com/api/narrative.php/session/latest

Getting a token

This is not a Twitter or X developer key, and there is no sign-up form on the site. The operator of that world creates a shared secret for that host and gives it to you. Staging and production use different secrets. Put the value only in the Authorization: Bearer or X-Narrative-Token header — never in the URL. How the operator writes the secret on the server is not documented on this public page.

Errors

SituationHTTPBody
Token file missing or empty404not_found
Missing or wrong token401unauthorized
Unknown path404unknown_resource
POST, PUT, or anything but GET405method_not_allowed
/players or /alliances without session_start400session_start_required
/oasis without from and to400from_and_to_required
/session/… with no data and outside a window404no_session
OPTIONS (browser preflight)204empty

Error bodies look like {"ok":false,"error":"unauthorized"}. A 401 also sends WWW-Authenticate: Bearer.

Pages

/sessions, /snapshots, /events, and /chat are paged. /session/… is one payload.

QueryMeaning
limitPage size. Default 200, maximum 500.
since_idExclusive cursor. Row id, except /sessions where it is session_start.
next_idFirst id of the next page, or null when the list is finished. Send it back as since_id.
include_payload=0Drop JSON blobs on snapshots and events.

A session bundle caps each list at 2000 rows and sets truncated: true if any list overflowed. Page /events and /chat yourself when that happens.

A chapter pull

  1. GET /meta — timezone and the clock windows.
  2. GET /sessions — which play windows already have snapshots.
  3. GET /session/latest or GET /session/{unix} — one window.
  4. GET /oasis?from=&to= — clear, late hopper, and ambush for that span.
  5. Charts across many windows: GET /snapshots, walking since_id.

session_start=latest means the newest snapshot window, else the newest event window, else the current play window (0 when the game is closed).

Resources

GET / or /meta

World name, server, timezone, speed, commence, current_session_start (0 outside play hours), and the window list. No table read.

GET /sessions

Play windows that already have snapshot rows. Each item: session_start, villages, players, pop, off_power, troops. Sums use the preferred portrait: close when that window has a close, otherwise open. Open and close are never added together.

GET /snapshots

One row per village per window. Preferred portrait unless you ask otherwise.

QueryMeaning
session_startlatest or unix. Omit it to walk history with since_id.
kindDefault preferred. open / 0, close / 1, or all (both; do not double-count).
uid wref alliance_idFilters. alliance_id may be 0.

Fields: session_start, kind (0 open, 1 close), taken_at, uid, player_name, alliance_id at snapshot time, wref, village_name, pop, hourly wood_prod clay_prod iron_prod crop_prod (crop_prod is after upkeep and can be negative), warehouse_capacity, granary_capacity, off_power (field attack, without catapults, rams, chiefs, or settlers), def_inf_power, def_cav_power, catapults, rams, chiefs, troop_count, wall_level, cranny_capacity, trapper_traps, ap, dp. payload is units (u1… and hero) and tribe 1, 2, or 3, unless include_payload=0.

GET /players and /alliances

Rollups for one session_start (latest allowed). Required. Same kind query as snapshots. The response includes kind: preferred, open, close, or all.

Players, sorted by population: uid, name, alliance_id, villages, pop, the four productions, both capacities, attack and defense powers, catapults, rams, chiefs, troop_count, cranny_capacity, trapper_traps, wall_level (maximum), ap, dp.

Alliances: alliance_id, players, villages, pop, productions, capacities, off_power, troop_count, catapults, chiefs. alliance_id 0 is unaffiliated.

GET /events

Facts as they happened. Fight size (skirmish, battle, great battle) is not stored. Compute it from these rows and the snapshots.

QueryMeaning
session_startEvents tagged with that window. 0 is off-hours.
from toEvent time range, inclusive, unix.
typeComma list, for example battle,raid,conquest.
actor_uid target_uidWho acted, who was hit.
typeMeaning
battle raid scoutCombat.
conquestVillage taken.
village_destroyedRazed.
building_completeA building finished. payload.notable marks Palace, Residence, Treasury, Wonder, walls, and milestones.
ww_progressWonder level.
artifactClaim.
hero_deathAttacker or defender hero.
alliance_create alliance_join alliance_leave alliance_kick alliance_warAlliance life.
medals_weekWeekly ribbons.

Shared fields: id, time, session_start, type, actor_uid, target_uid, from_wref, to_wref, troops_attacker, troops_defender, losses_attacker, losses_defender, resources_moved, payload (names and unit breakdowns at that moment).

An oasis fight with Nature as target_uid can still be a player waiting on the tile. Use /oasis to split clear, late hopper, and ambush.

GET /oasis

Requires from and to (unix). Labels each oasis fight clear (animals only), late_hopper (empty tile), or ambush (a player defense was already there). A player tribe on the defender side proves an ambush even when the tile owner is still Nature.

The body includes counts, the three lists, and ambush_gate. Say there were zero ambushes only when notices_scanned and reports_scanned are true and ambush_count is 0. An ambush row may carry defender_uid for the writer. The published reading names the raider only.

GET /chat

Public channel and alliance chat. Private messages are never in this API.

QueryMeaning
from toMessage time.
scopeglobal, or an alliance id.
uidAuthor.

Fields: id, chat_id, time, uid, name, scope, msg.

GET /session/latest or /session/{unix}

One play window: session_start, session_end, kind, label, truncated, then snapshots, players, alliances, events, and chat. Events fall inside the window. Chat is that range plus 30 minutes on each side. Snapshots use the preferred portrait. An empty snapshot list is normal until the window has been recorded.