Getting started
The ledgers' API
A faction's master and a business's owner can read their ledgers from their own programs - a Discord bot, a spreadsheet, a dashboard - with a key from the account site. Read only: nothing in the realm can be changed through it.
Your key
On the account site, Account > API keys, choose the character and Make a key. A key is made for a character who leads a faction (its master) or owns a business. It reads:
- while that character is the faction's master: its coffers ledger and their days, each member's contributions, the members' activity, the storage logs, its territory and Authority, its diplomacy, its members' trade packs and supply orders;
- for each business that character owns (and each business of the faction while they are its master): its ledger, its stock and its sales.
It never shows where anyone or anything is: no member's position or online status, no trade pack's place. The key is shown once: copy it then and keep it like a password - anyone holding it reads all of that. An account holds three keys at most. Revoke a key the moment you think it leaked: it stops at once. The rights are checked again at every call: a master who steps down or leaves, or a business sold, and the key reads nothing more of it.
Plans
| Calls a day | Price |
|---|---|
| 100 | Free |
| 1,000 | 100 KP for 30 days |
| 10,000 | 500 KP for 30 days |
A plan counts for 30 days from the payment; buying the same plan again adds 30 days after the days you have left (another plan starts at once, and the days left on the old one are not carried over). Renew automatically is off until you turn it on: then the KCD Points are taken again when the 30 days end, and if you are short of them the key goes back to the free 100 a day and the renewal turns off. The day's count starts again at 00:00 UTC. The free 100 calls are the account's: all its free keys share them (a paid key has its own). Whatever the plan, an account makes 60 calls a minute at most, one at a time (wait for an answer before the next call), and at most five keys a day.
Calling the API
Every call is a GET to https://account.kcdroleplay.com/api/ucp/v1/..., with the key in the header (never in the address - addresses end up in logs):
curl -H "Authorization: Bearer krp_your_key_here" https://account.kcdroleplay.com/api/ucp/v1/meThe answers are JSON. Times are UTC (ISO 8601), money is in groschen.
| Route | What it gives |
|---|---|
GET /me | the key: its character, server, faction (when they are its master), plan, today's calls and limit |
GET /faction/ledger | the faction's coffers: every deposit, withdrawal, wage, tax and payment, with its member and note (pages) |
GET /faction/treasury | the coffers' balance now, and each day's money in, out and net |
GET /faction/contributions | each member's money into and out of the coffers over a period |
GET /faction/members | the members: rank, joined, last day played, hours in all, this week and the four weeks before |
GET /faction/storage | every piece and load put into or taken from the faction's chests (pages) |
GET /faction/storerooms | the same for the store rooms of the faction's houses (pages) |
GET /faction/territory | the towns and Authority holdings it holds, its Authority points by town, its Authority type and bank |
GET /faction/diplomacy | its alliances, wars and offers between factions, and the Authority wars it takes part in |
GET /faction/tradepacks | the trade packs its members made over a period: kind, maker, origin, value, sold or not, price (pages) |
GET /faction/orders | the supply orders its members delivered over a period, by member and by recipe |
GET /businesses | the businesses the key reads, with their ids |
GET /business/ledger?business=<id> | a business's ledger: each stocking, taking back, price change and sale - who, the ware, how many, the price, the total, whose stock it was (pages) |
GET /business/stock?business=<id> | the counter now: each ware, its quantity, price and condition, and the till |
GET /business/sales?business=<id> | the sales over a period, day by day and ware by ware |
Pages of rows
The ledgers come 100 rows at a time at most (limit=1..100), by the row's id:
- Newest first (no cursor, or
before=<id>): to read back through the history. Whenmoreis true, ask again withbefore=thenextvalue. - Only what is new (
after=<id>): oldest first, from that row on. Keep the highest id you have and ask with it every few minutes - the cheapest way to stay up to date.
Filters: on /faction/ledger, dir=in|out and a period from=YYYY-MM-DD, to=YYYY-MM-DD (UTC days, both included); on /business/ledger, kind=stock|withdraw|price|sale. The same call made again within 30 seconds is answered from memory.
{
"faction": { "id": 12, "name": "House of Ostrov" },
"order": "newest first",
"more": true,
"next": 48210,
"rows": [
{ "id": 48311, "at": "2026-10-25T09:14:02Z", "amount": -250, "note": "wages", "member": "Jan Novak" }
]
}A small Python loop that keeps a copy up to date:
import os, time, requests
KEY = os.environ["KRP_API_KEY"]
URL = "https://account.kcdroleplay.com/api/ucp/v1/faction/ledger"
last = 0
while True:
r = requests.get(URL, params={"after": last} if last else {"limit": 100},
headers={"Authorization": "Bearer " + KEY}, timeout=20)
if r.status_code == 429:
time.sleep(int(r.headers.get("Retry-After", 60))); continue
r.raise_for_status()
rows = r.json()["rows"]
for row in rows: print(row)
if rows: last = max(row["id"] for row in rows)
time.sleep(300) # every five minutes: 288 calls a dayThe routes in detail
Every route below is a GET under https://account.kcdroleplay.com/api/ucp/v1. A period is from=YYYY-MM-DD and to=YYYY-MM-DD (UTC days, both included) or days=N (the last N days); 30 days when none is given, 366 at most. Pages means the limit, before and after above, and an answer with order, more, next and rows.
| Route | Asks | Answers (each row) |
|---|---|---|
/me | - | character {id, name, server}, faction {id, name} or null, tier, dailyLimit, usedToday, paidUntil, perMinute |
/faction/ledger | pages, dir=in|out, a period | id, at, amount (+ in, - out), note, member |
/faction/treasury | a period | balance; days: day, in, out, net |
/faction/contributions | a period | members: id, name, in, out, net, entries |
/faction/members | - | weeks (the Mondays, this week first); members: id, name, rank, rankName, joined (a day, when known), lastPlayed (a day), hoursTotal, hoursThisWeek, hoursByWeek (as weeks), deceased |
/faction/storage | pages | id, at, chest, member, item, good (a trade good), amount (+ in, - out), quality |
/faction/storerooms | pages | id, at, house, member, good, amount (+ in, - out) |
/faction/territory | - | authority {type, mercenary, bank}; towns: town, name, land; holdings: id, town, name, kind, land; authorityPoints: town, land, points |
/faction/diplomacy | - | relations: id, kind (alliance, war...), status, with {id, name}, proposedByUs, reason, since; authorityWars: id, status, casus, declared, attacker, defender |
/faction/tradepacks | pages, a period | id, type, member, origin, value, packed, ended, sold, soldFor |
/faction/orders | a period | members: id, name, deliveries, qty, paid; recipes: recipe, deliveries, qty, paid |
/businesses | - | businesses: id, name, owner (character or faction) |
/business/ledger | business, pages, kind=stock|withdraw|price|sale | id, at, kind, member, item, health, qty, price, previousPrice, total, supplier |
/business/stock | business | till; wares: item, health, shelf (an inn's shelf), qty, price |
/business/sales | business, a period | days: day, qty, total; wares: item, qty, total |
A business's ledger, stock and sales are its present owner's: a business bought from someone else starts a new ledger for its new owner. Item names are the game's own keys (beer, bandage_classic...).
Errors
| Status | Meaning |
|---|---|
| 401 | no key, a malformed key, or a key revoked or never made (too many wrong keys from one address: 10 minutes' wait) |
| 403 | the key's character no longer has the right (not the master any more, the business sold) or the business is not theirs |
| 404 | no such route |
| 429 | 60 calls in the minute, the day's calls used up, or a call sent before the last one answered - wait the seconds in Retry-After |
| 503 | busy for a moment, or a read that took too long (ask for a shorter period) - try again a few seconds later |
