---
name: set-character-stats
description: Reference for Set's nine base character stats. Use when sending a stats parameter in the right order, reading the schema of the stats endpoint and of the stats, modifiedStats and finalStats blocks on a character, telling the five primary stats from the four situational ones, or respecting the stat bounds and the Perfect value.
license: Free to use when obtained from set.world, commercially too (the API, what it returns, the skills and downloaded models). The source code of Set is © Jimmy Lee under CC BY-NC 4.0 and its commercial use needs a paid waiver.
metadata:
  version: "0.8.9"
  title: Stats
---

# Stats

Every character has nine base stats, each an integer from 8 to 24. A stat of 24 is shown as **Perfect**. This skill owns the stat order and bounds.

```sh
curl https://set.world/api/stats               # JSON
curl 'https://set.world/api/stats?format=csv'  # index,stat,primary,min,max
```

## Schema

```ts
type StatName = 'strength' | 'dexterity' | 'intelligence' | 'wisdom' | 'agility' | 'vitality' | 'perception' | 'resolve' | 'luck';
type StatBlock = Record<StatName, number>;

type StatsResponse = { stats: StatName[]; min: 8; max: 24; perfect: 24; note: string };
```

```jsonc
{
  "stats": ["strength", "dexterity", "intelligence", "wisdom", "agility", "vitality", "perception", "resolve", "luck"],
  "min": 8,
  "max": 24,
  "perfect": 24,
  "note": "…"   // one sentence restating the order and the bounds
}
```

The CSV, complete:

```csv
index,stat,primary,min,max
0,strength,true,8,24
1,dexterity,true,8,24
2,intelligence,true,8,24
3,wisdom,false,8,24
4,agility,true,8,24
5,vitality,true,8,24
6,perception,false,8,24
7,resolve,false,8,24
8,luck,false,8,24
```

## The canonical order

The order above is part of the contract. Every `stats=` parameter takes nine dash-joined integers in it:

```text
stats=16-15-12-11-15-18-12-13-9
      str-dex-int-wis-agi-vit-per-res-luck
```

```js
const ORDER = ['strength', 'dexterity', 'intelligence', 'wisdom', 'agility', 'vitality', 'perception', 'resolve', 'luck'];
const statsParam = ORDER.map((stat) => character.finalStats[stat]).join('-');
```

Endpoints that take `stats=` require all nine, each an integer in 8 to 24; anything else is a 400.

## Primary and situational stats

Only the five **primary** stats (strength, dexterity, agility, intelligence, vitality) feed the 23 derived attributes. The others (wisdom, perception, resolve and luck) are rolled, changed by traits, shown on the sheet and counted in the power rating, but no attribute formula reads them. They are reserved for your game: dialogue checks, loot luck, morale, whatever you need.

| Primary stat | Mainly drives |
| --- | --- |
| strength | Physical damage and carrying |
| dexterity | Action damage, attack speed, critical chance |
| intelligence | Magical damage, cast speed, magic reduction, vision, clarity |
| agility | Dodge, walk speed, jump, initiative, reflexes |
| vitality | Health, stamina, physical reduction, resistances |

The formulas are in [Calculations](https://set.world/skills/calculations).

## The three blocks on a character

| Field | Meaning |
| --- | --- |
| `stats` | The roll: nine independent uniform integers in 8 to 24, plus `level` (always 1) and the trait counts |
| `modifiedStats` | After advantages and disadvantages, each stat clamped to 8 to 24 |
| `finalStats` | What to play with. Equal to `modifiedStats` unless the character was rolled with `equipmentBonus=1` |

A filled example of all three is in [Rolling a character](https://set.world/skills/rolling-a-character).

Send `finalStats` to `/api/attributes`, `/api/power`, `/api/drop` and the combat fallback. Never reapply traits.

## Changing a stat

Set grants no stat points and has no level curve. Traits change stats at birth ([Calculations](https://set.world/skills/calculations)); the optional equipment bonus adds to them ([Slots](https://set.world/skills/equipment-slots)); and a stat increase has a price in orbs ([Crafting an item](https://set.world/skills/crafting-an-item)). Whether and how a character grows is your game's rule, and stats above 24 exist only in your own state:

```ts
type StatGrowth = { characterId: string; stat: StatName; from: number; to: number; orbsPaid: number; at: string };
```
