---
name: set-api
title: Set World API
description: Generation, grading, and pricing primitives for games built on Set World. Covers stateless character/item APIs, crafting, probabilities, derived attributes, trait impacts, and consumer-owned combat and progression.
homepage: https://set.world
spec: https://set.world/api/spec
license: MIT
version: 1
methods: [GET]
auth: none
cors: open
content_type: text/markdown
canonical_paths:
  - https://set.world/skill
  - https://set.world/skill.md
  - https://set.world/.well-known/skill
  - https://set.world/.well-known/skill.md
  - https://set.world/llms.txt
  - https://set.world/api/skill
---

# Set World API

Set is an open fantasy RPG system for game developers and agents. It provides procedural characters and items, a single-currency pricing layer, 144 character classes, 288 skills, 48 status-effect names, 23 derived attributes, and deterministic trait impacts. Generator and economy requests return JSON over HTTP GET; the agent guides themselves return Markdown.

**Build your game on Set.** Use these APIs as the backend for a roguelike, a MUD, a card game, an idle clicker, a tabletop companion, a narrative engine, or anything else that needs RPG mechanics. Every system is composable: roll items independently, score them, craft toward target tiers, derive attributes from stats, price enemy drops, and interpret equipment budgets in your own game. The formulas are open, the data tables are MIT-licensed, and the API is CORS-enabled for any origin.

This skill is the human-and-agent-readable guide. The machine-readable surface map (every endpoint, query params, summary, and a two-line `scenario`) lives at `GET /api/spec`. Start with `/api/spec`, then inspect the relevant response and math contract. Discovery and guide text are maintained alongside the handlers; PLAN.md records the implementation and verification status of the contract repairs.

## Conventions

- **Method**: `GET` only. Body-less.
- **Encoding**: parameters are in the query string; structured overrides are URL-encoded JSON. Successful JSON responses return their payload directly. Guide endpoints return Markdown.
- **Errors**: handlers use `{ error: { code, message, field? } }`, normally HTTP 400 for validation. Supplied malformed options are distinct from omission. Repeated query parameters use their first value. An empty optional `seed=` remains unseeded; empty budgets, stats, booleans, and vectors are invalid. Integer-valued numeric spellings such as `1e2` remain accepted where they satisfy the domain.
- **CORS**: open for `GET`, `POST`, `OPTIONS` from any origin.
- **Statelessness**: API generation and crafting do not persist results. `/roll/character` is the separate page route that creates an immutable encrypted birth certificate in Postgres.
- **Seeds**: use a uint32 seed and retain the operation/mode, all effective inputs, and matching source/content rules for reproducibility. Expand a roster with the public `deriveSeed(seed, i)` (implemented using `Math.imul` for uint32 arithmetic), one character request per member.
- **Content version**: `contentVersion` is `3.<fingerprint>`: an explicit rules revision and a case-sensitive base64url-encoded 128-bit SHA-256 fingerprint of structured, ordered generation tables, including returned prose and metadata. Strings retain their Unicode form; trait/theme hashing is unchanged. Output-affecting code changes require an explicit revision bump. This replaces the old `1.<weights>.<tables>` stamp, so old preview-to-birth links need a fresh roll. Preserve full objects or the matching source/content release for history; a live server need not serve an old snapshot.
- **Single-flight**: API item/set/character, craft, and drop generation and the item/character creation pages enter a process-local forge queue after validation. Nested drop crafting remains synchronous inside its parent flight. There is no batch-creation endpoint or fleet-wide queue guarantee.
- **Stat order**: when an endpoint takes `stats=`, the order is fixed: `strength, dexterity, intelligence, wisdom, agility, vitality, perception, resolve, luck` (9 dash-joined integers). Always confirm via `GET /api/stats`.
- **Stat domain**: `/api/attributes`, `/api/power`, and `/api/drop` require every stat to be an integer in `[8,24]`. The local attribute helper retains its clamping behavior. Power levels are positive integers bounded by safe representation of the maximum rating; `/api/spec` publishes the bound. This is a numeric limit, not a level curve.
- **Item input**: appraisal routes accept exactly one of `indexes` or `rolls`. Every one of the 19 entries must be an in-range integer, including inactive factors. Salvage additionally accepts a tier alone, or no input for its schedule; malformed input never selects the schedule.
- **Primary stats**: only 5 of the 9 stats — `strength, dexterity, agility, intelligence, vitality` — power the derived-attribute formulas. The other 4 (`wisdom, perception, resolve, luck`) are still rolled, traited, and displayed, but they don't directly compute derived attributes; that keeps the formula stable when stats are added or renamed.
- **Slot order**: equipment iteration uses `EQUIPMENT_SLOT_ORDER` from `/api/slots`.
- **Grade scale**: items are graded F through S (seven grades), determined solely by material. The UI displays "Grade F" … "Grade S" — no fantasy tier names. Definitions: `GET /api/rarity/tiers`.
- **Material rank**: `materialRank` is scarcity order within a material table (23 tool materials, 30 wearable materials), with 1 most common. Grade comes from cumulative weight share; rank alone is not a letter grade or probability.

## Discovery

Start with `GET /api/spec`. It returns `{ version, endpoints: [{ method, path, query?, summary, scenario: { use, returns }, workspace: { title, description }, example? }] }`. The scenario supplies the home page's API reference; `workspace` supplies an action title and short description for each prepared endpoint column. These are discovery labels, not executable demos or generation inputs.

```sh
curl https://set.world/api/spec
```

### Choose how much of Set to use

**One identity:** request `/api/roll/character?seed=42`. Keep the complete response,
including its class, skills, traits, `finalStats`, attributes, equipment, seed,
and `contentVersion`. Give it a name or identifier in your application. The seed
reproduces a roll at that snapshot; it is not authentication or a unique person.
No account, crafting integration, or birth-certificate write is needed. To keep
an optional public birth sheet, use the separate `/roll/character` page route
described below; it records the original roll, not your evolving identity.

**A game:** begin with the same character response, then read `/api/stats`,
`/api/slots`, `/api/attributes/spec`, and `/api/modifiers/spec`. Your game supplies
combat and concrete equipment effects. After a victory it can price a drop with
`/api/drop`, price a stat increase with `/api/boost/cost`, craft through `/api/craft`,
and appraise discarded gear through `/api/salvage`. Read `/api/craft-guide` for the
full loop. Keep current stats, inventory, orb balance, rewards, and history in
your own state. Expand rosters with `deriveSeed`, one request per character.

`/api` and `/api/roll` return a greeting only. They identify a reachable route;
they neither generate an identity nor check character storage.

The home page's sixth column illustrates a consumer of these objects: Generate
armies requests 32 level-one characters individually and displays two teams of
sixteen on a board. Its movement, damage, and temporary health/stamina are browser-local
example rules. The API supplies no complete-battle operation, saved combat state, or
rewards. Portrait-free cards show class, level, and live resource bars; class
names link to the original birth sheets.

### Optional experimental combat

If your game needs a starting point, read the
[basic-lightweight-combat skill](https://set.world/basic-lightweight-combat).
`GET /api/basic-lightweight-combat?mode=damage` resolves one attack from
reconciled attacker/defender stats, with physical/magical/action kinds, optional
current resources/recovery time, and an optional uint32 seed. It returns damage,
rolls, and suggested resource changes. `mode=initiative` schedules a supplied
actor list over a time window, returning who acts first and a move count per
actor. A move means an action opportunity, not a tile or guaranteed attack.

All results carry `experimental: true`, `rulesVersion`, and `contentVersion`.
The machine-readable profile is `/api/basic-lightweight-combat/spec`; the
Markdown source is served at `/api/basic-lightweight-combat/skill`. It excludes
status/weapon effects and persistent battle state. Skill-based games can ignore
it. Your game chooses targeting, cooldown enforcement, resource application, and
progression; no API call saves these suggested changes.

Revision 3 introduces this explicitly authorized fallback without changing the
existing generator draws or economy. Older preview stamps, including revision 2,
need fresh rolls before creating birth sheets. Existing stored births are retained.

Supplementary tables that an agent typically needs once before composing other calls:

| Endpoint | Why |
| --- | --- |
| `/api/stats` | Canonical stat order and `[min, max]` bounds before sending `stats=` in a query. |
| `/api/slots` | Slot list, per-slot capacity (hand and finger hold two), and the derived-attribute domain each slot influences. |
| `/api/drop/classes` | Encounter classes (`trash`, `veteran`, `elite`, `boss`, `world-boss`) and their drop multipliers (1, 3, 10, 50, 250). |
| `/api/rarity/tiers` | Seven grade definitions and material-rank counts; 23 tools and 30 wearables are material counts, not extra grades. |
| `/api/salvage` | The disassembly schedule (F–C: 0, B: 2, A: 40, S: 200 orbs) and the strict-sink expectation that keeps it honest. |
| `/api/modifiers/spec` | The item power budget per grade, the 31 theme channels, and the hash rule that derives them. |
| `/api/attributes/spec` | Formula behind every derived attribute so a client can recompute locally. |

## Generators

### Roll a single item

```sh
curl https://set.world/api/roll/item
curl 'https://set.world/api/roll/item?seed=42'        # fixed request and snapshot
```

Returns a fresh item enriched with `score, materialRank, tier, tierGrade, tierName, orbValue, material: { name, materialRank, tier, tierGrade, tierName }`, `affects` (the slot's derived-attribute domain), a one-row `breakdown` matching the per-slot shape from `/api/roll/set`, the `contentVersion` string, and the `seed` that produced it (`null` when unseeded). `tierName` returns grade labels (`'Grade F'` … `'Grade S'`); `tierGrade` returns the raw letter. The human-facing URL `/roll/item?seed=42` (no `/api`) generates the same item as the API at that seed and content snapshot, then redirects to the full weighted-table visualization with a permalink encoding the 19-number raw roll vector. Omit the seed for a fresh random roll. An already generated or crafted item opens directly at `/roll/item/<item.roll joined by dashes>`.

### Roll a full equipment set

```sh
curl 'https://set.world/api/roll/set?seed=7'
```

Returns `{ equipment, orbValue, orbBreakdown, seed, contentVersion }`. `orbBreakdown` walks `EQUIPMENT_SLOT_ORDER` and emits one row per slot with `affects` and the items inside.

### Roll a character (one at a time)

```sh
curl https://set.world/api/roll/character
curl 'https://set.world/api/roll/character?seed=2026'                  # fixed request and snapshot
curl 'https://set.world/api/roll/character?seed=2026&equipmentBonus=1'  # fold gear bonuses into finalStats
```

Returns base `stats`, `modifiedStats` (base reconciled with trait deltas, clamped to `[8, 24]`), `equipmentBonus` (bool), `equipmentBonuses`, and `finalStats`. Equipment→stat bonus is opt-in: on a fresh roll `finalStats === modifiedStats`; pass `equipmentBonus=1` to fold the grade-gated per-slot gear bonus into `finalStats`. Also returns `equipment` (enriched), `powerRating` / `powerRatingMax` (a whole-character heuristic — a roster may sum these by its own rules), `equipmentOrbValue`, `equipmentOrbBreakdown`, `traits` (skills carry `flavor`; advantages/disadvantages each carry their FNV-1a-derived `impact`), `class`, the `contentVersion` string, the `seed`, and the twenty-three derived `attributes`. An army is a set of per-soul derived seeds via `deriveSeed` — one call per soul — so a whole roster is shareable and verifiable given its complete request recipe and available snapshot.

For a human-facing character sheet, `/roll/character?seed=2026` creates a new encrypted birth certificate and redirects to `/roll/character/<uuid>`. It preserves the originally rolled character with its seed and content snapshot, leaving equipment bonuses off. An optional `contentVersion=` must match the running snapshot; an outdated version returns a readable 409 page before generation or persistence. The optional `name=` is a UUIDv4 display name, preserved when a home preview or party member opens its detail page; omitting it creates one on the server. This name is separate from the database row UUID and does not alter the stateless API’s seeded response. Saving a home-page party member uses this route with that member's derived seed, snapshot, and display name. The API roll remains stateless; the page route requires Postgres.

The stored-character page distinguishes invalid IDs (400), absent records (404),
unavailable storage (503), and unreadable data (500). It retains legacy birth
records without optional metadata. When the birth's version differs or is unknown,
the sheet labels its current appraisal version separately without rewriting the birth.

## Rarity

### Score a known item

```sh
curl 'https://set.world/api/rarity?indexes=0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0'
```

Pass either `indexes=` (selected table-entry positions) or `rolls=` (the raw 19-number roll vector). Returns `score, materialRank, tier, probability, orbValue, material: { name, materialRank, tier, tierGrade, tierName }`, and a `breakdown[]` of per-factor `−log10(p)` contributions sorted descending. The item's letter grade is determined solely by the rolled material; the rarity score measures the combination probability separately.

### Tier definitions

```sh
curl https://set.world/api/rarity/tiers
```

## Economy: orbs

The whole economy is denominated in a single currency (orbs). Every cost is precomputed and deterministic — the same inputs return the same result every time, so you can verify any cost by calling the endpoint (pass `seed=` to pin a roll).

### Crafting (rejection-sample to a target tier)

```sh
curl 'https://set.world/api/craft?tier=5'
curl 'https://set.world/api/craft/cost?tier=5'   # up-front price + budget
```

`craftCost(T) = 5^(T-1)` → `1, 5, 25, 125, 625, 3125, 15625` orbs for Grade F..S. The server rejection-samples until the material grade hits or the budget (`min(1_000_000, 100 × craftCost(T))` by default) runs out (`capped: true`). An explicit positive integer budget is capped at 1,000,000; the response reports that effective budget. Invalid budgets fail, and budget is supported only in tier mode.

### Best-of-N lottery

```sh
curl 'https://set.world/api/craft?orbs=125'
```

Returns the single highest-tier item across `N` independent rolls (ties broken by rarity score), with `orbs` and `rolls` both reporting the effective count (capped at 100,000). `rollsExpected` retains the nearest historical sample's median and score bands, labeled with `referenceOrbs` and `method: "historical-sample"`. The separate `gradeExpectations` has `method: "exact-weighted-model"`, actual `rolls`, `medianTier`, `medianGrade`, and seven `distribution` rows containing `tier`, `tierGrade`, exact-grade `probability`, `atLeastProbability`, and `cumulativeProbability` (best grade ≤ this grade). At six orbs the actual median is B; the five-orb score sample remains labeled as such. No new trials run to estimate these grade statistics.

Both crafting modes enrich `item` and include its canonical `item.breakdown` slot row. Orb crafts also return `analysis`: the exact combination's single-roll probability, the probability of reaching its grade or better per roll and across the craft, rarity/material-rank/orb-value ceilings, the fraction of the rarity ceiling, and six weighted rarity factors. The ceiling fraction measures logarithmic rarity score, not a percentile.

### Stat boost

```sh
curl 'https://set.world/api/boost/cost?from=14&to=18'
```

`boostCostStep(s) = (s-7)^3` for `8 ≤ s ≤ 20`, then `4096 / 8192 / 32768` for the perfect wall steps `21/22/23`. Total `8 → 24 = 53,337` orbs.

### Monster drops

```sh
curl 'https://set.world/api/drop?stats=12-14-10-11-13-16-12-14-11&class=elite'
```

`baseDrop = round((avgStat - 6)^2 / 4)` × encounter-class multiplier × `uniform(0.75, 1.25)` variance. Optional `override=` and `seed=` parameters are documented in `/api/spec`; `override.guaranteedTier=1..7` requests a material-grade floor on a derived seed and returns `guaranteedItem` (an enriched item plus its `salvage` value). Its sibling `guaranteedItemCraft` reports `requestedTier`, derived `seed`, effective `budget`, `attempts`, and `capped`. Inspect the actual grade and cap outcome. The response echoes the parent seed (null when unseeded) and `contentVersion`.

Overrides accept only `flat`, `multiplier`, `guaranteedTier`, and `bonusOrbs`.
Flat amounts must be non-negative safe integers; multipliers are finite in
`[0,1000000]`; bonus bounds satisfy `0 ≤ min ≤ max ≤ 1000000000`. Flat plus the
maximum bonus must remain safely representable. Unsupported fields and inherited
encounter-class names are rejected before generation.

### Salvage (disassembly)

```sh
curl 'https://set.world/api/salvage?tier=6'                  # by grade
curl 'https://set.world/api/salvage?indexes=<19-numbers>'    # appraise a known item
curl 'https://set.world/api/salvage'                         # schedule + sink invariant
```

The salvage schedule is F–C: 0, B: 2, A: 40, S: 200 orbs. The expected ordinary paid, unselected one-orb draw returns about 0.6964 orbs, and expected best-of-N salvage is below N. This is not a fixed loss on every outcome or an enforced policy for free rolls or chosen seeds. The endpoint appraises the item; the game decides whether it can be redeemed.

### Leveling is yours (levels are meaningless here)

Set grants no stat points and publishes no level curve. `/api/drop` prices a nine-stat block in its accepted domain. Quadratic base drops and cubic/geometric prices do not establish pacing for every game: encounter mix, fight frequency, overrides, and combat utility are the client's design. Where `level` appears, it is the client's number, weighted by the power heuristic but not interpreted as progression.

### Power rating (whole-character grading)

```sh
curl 'https://set.world/api/power?stats=14-12-10-11-13-16-12-14-11&skills=2'
```

One canonical number per character: `level × 100 + (str + int + dex + agi + vit) × 10 + (wis + per + res) × 5 + luck × 2 + skills × 25`, computed from the reconciled (final) stat block. `/api/roll/character` already includes `powerRating` and `powerRatingMax`; use this endpoint to re-grade characters you store yourself. Grading, not prescription — matchmaking rules stay with your game.

### Item power budgets (modifiers)

```sh
curl 'https://set.world/api/modifiers?indexes=<19-numbers>'
curl 'https://set.world/api/modifiers/spec'
```

Items never ship resolved stat modifiers. What Set grades is the **budget** — how much power an item of a given grade is entitled to (`F: 0, E: 1, D: 2, C: 4, B: 8, A: 16, S: 32` — budget doubles per grade while craft price grows 5×) — plus a **themed channel** for each name factor (prefix/quality/material/gear/suffix), hash-derived by the same pinned FNV-1a spec as traits into one of 31 channels (the 23 derived attributes + 8 elemental channels: fire, frost, lightning, poison, shadow, holy, arcane, nature). What a point of budget buys inside your combat math is your tuning knob; two games honoring the same Grade A item at different magnitudes are both correct.

## Traits

```sh
curl 'https://set.world/api/traits/impact?name=Iron%20Will&kind=advantage'
curl 'https://set.world/api/traits/impacts?kind=advantage'   # bulk pre-scored map
```

Every trait name hashes (FNV-1a 32-bit, offset basis `0x811c9dc5`, prime `0x01000193`, UTF-8 NFC) to deterministic stat deltas. The pinned byte-modulo mapper has tier shares 68.75/19.53125/9.375/2.34375% over 256 byte values; the current 144-entry pools have their own tier counts (advantages 100/28/11/5, disadvantages 100/31/10/3). The 60/25/12/3 threshold intervals are not population percentages. Advantages use `+5/+10/+15/+25%` primary, disadvantages `-8/-15/-22/-35%` primary.

## Derived attributes

```sh
curl 'https://set.world/api/attributes?stats=14-12-10-11-13-16-12-14-11'
curl https://set.world/api/attributes/spec
```

Twenty-three derived attributes — max health, stamina, physical/magical/action damage, six damage-reduction/resistance/dodge channels, six speed channels, carry capacity, jump height, vision range, crit chance, plus the three combat-utility channels `clarity` (anti-dodge accuracy), `initiative` (cooldown rate), and `reflexes` (counter to surprise hits) — each computed as `base + primaryCoef × (primary - 8) + secondaryCoef × (secondary - 8)` after the 5 primary stats are clamped to `[8, 24]`. Every primary and secondary in the formula table lives in `{strength, dexterity, agility, intelligence, vitality}`, so adding or renaming a non-primary stat can never break the derivation. `/api/attributes/spec` returns the full formula table.

## Recipes

### Build a complete level-1 character

```sh
curl https://set.world/api/roll/character
```

Single call: 9 base stats, modifiedStats, finalStats, traits with impacts, full equipment, orb-equivalent value of the loadout, power rating, twenty-three derived attributes.

### Mint two armies and price the battle

```sh
# side A: base seed 1, 40 souls — one call per derived seed
curl 'https://set.world/api/roll/character?seed=1'   # soul 0
curl 'https://set.world/api/roll/character?seed=<deriveSeed(1,1)>'  # soul 1 … through soul 39
# side B: base seed 2, 40 souls, same fan-out
curl 'https://set.world/api/roll/character?seed=2'   # soul 0 …
```

Retain each army's base seed, count, request parameters, and matching content/rules release. `deriveSeed` reconstructs per-member seeds. Summed `equipmentOrbValue` or `powerRating` can support a game-defined roster budget, but do not prove fair combat. Replaying a battle additionally needs the consumer's rules and event history.

### Price a fight

```sh
curl 'https://set.world/api/drop/classes'
curl 'https://set.world/api/drop?stats=...&class=boss'
```

### Craft up to Grade B

```sh
curl 'https://set.world/api/craft/cost?tier=5'   # → 625 orbs
curl 'https://set.world/api/craft?tier=5'        # → requested floor B; inspect returned grade and capped
```

### Appraise a supplied item

A consumer that tracks items by index vector can re-derive everything from the indexes alone:

```sh
curl 'https://set.world/api/rarity?indexes=<19-numbers>'
```

## Reference Codexes

Set exposes the reference tables listed below as endpoints. The nineteen weighted item tables also live in the source repository's `sets/` directory; do not assume every source table has a JSON endpoint.

| Endpoint | What you get | Build with it |
| --- | --- | --- |
| `/api/skills` | 288 skills with flavor text | Skill trees, talent systems, character progression |
| `/api/advantages` | Advantage trait pool | Perk systems, character creation bonuses |
| `/api/disadvantages` | Disadvantage trait pool | Flaw systems, challenge modifiers, cursed items |
| `/api/classes` | 144 classes with mainhand weapon binding | Class selection UI, weapon-class gating, NPC archetypes |
| `/api/effects` | 48 status effects with prose descriptions | Combat status systems, buff/debuff mechanics, item enchantments |
| `/api/stats` | 9 base stats with bounds | Character sheets, stat allocation UI, NPC scaling |
| `/api/slots` | 13 equipment slots with capacity and domain | Inventory systems, loadout screens, equipment comparisons |
| `/api/attributes/spec` | 23 derived attribute formulas | Tooltip systems, stat previews, build planners |
| `/api/rarity/tiers` | Grade F-S definitions | Loot filters, item comparison, reward thresholds |
| `/api/drop/classes` | 5 encounter classes with multipliers | Enemy design, encounter balancing, reward scaling |

### What you can build

- **Roguelike / dungeon crawler**: generate characters and items and price drops/crafts. Keep complete generation recipes and the matching content release for replay. Your engine generates the dungeon, resolves combat, and decides what salvage carries into another run.
- **Autobattler / mass battle**: expand base seeds into per-character requests, render the returned attributes, and resolve combat in your engine. A salary cap built from PWR or orb values is a game convention, not a balance proof.
- **Idle / clicker game**: use orb economy (craft costs scale exponentially), stat boosts as prestige currency sinks.
- **Turn-based RPG**: read `initiative`/`reflexes`/`clarity` as turn order, ambush rounds, and hit confirmation; stamina and the cast/action charge speeds as your action economy; the 48 status effects as turn-native crowd control (durations and stacking are yours to define). Attribute units are advisory — the coefficients are the contract, so turn-meter readings are as legitimate as real-time ones.
- **Tactics / isometric board battles**: `walkSpeed` is tiles per turn, `jumpHeight` is obstacle traversal, `visionRange` is fog of war, `carryCapacity` is encumbrance. Movement range is a reading of existing attributes — no new math needed on either side.
- **MUD / text adventure**: character generation + classes + skills + effects supply characters and vocabulary; your game supplies interaction rules and narrative.
- **Tabletop companion**: roll characters at the table, use the trait impact system for deterministic modifiers, reference the attribute spec for combat resolution.
- **Card game**: each skill, class, or effect is a card; traits modify stats; equipment builds power rating.
- **NPC generator**: roll hundreds of characters via `/api/roll/character` to populate a world with mechanically distinct entities.
- **Build planner / theorycrafting tool**: `/api/attributes/spec` + `/api/boost/cost` + `/api/traits/impacts` supply prices and attribute data; an optimizer also needs your game's objective and concrete item/combat rules.

### Design principles for builders

1. **Reproducible recipes.** Trait impacts are pinned to the name/hash specification. Seeded generation requires the same operation, effective inputs, and matching content/rules snapshot. A seed alone is not a saved game.
2. **Composable, not coupled.** You can use the item system without characters, the economy without combat, the traits without equipment. Mix and match.
3. **Consumer-owned state.** The API does not hold inventories or wallets. Optional birth certificates record original characters. Per-entity formulas do not retune for roster size; this does not imply unlimited service throughput.
4. **Inspectable.** Use spec endpoints, returned breakdowns, ALGORITHMS.md, and the repository tables. The optional equipment-to-stat schedule is documented in ALGORITHMS §4.4 and implemented in `common/statbonuses.ts`.

## Source

The full source, conventions, and architecture: <https://github.com/jimmylee/set>. MIT licensed. Pages Router only. No client SDK.
