Skip to content

Game Data & Balancing

The Game Data editor is a spreadsheet interface for managing game balance. Create tables for XP curves, item stats, difficulty parameters, and more—then compare changes across versions.

Without Quest Data, a balance change means: edit code → rebuild → distribute build → testers wait. With Live Balancing, a designer edits a cell in the dashboard and the running game updates in under a second.

3 SDK calls. ~75 bindings. ~6 lines of game code:

func _ready() -> void:
for b in all_buildings:
QuestData.bind_balancing(b, "buildings", "", "building_id")
QuestData.bind_balancing_pivot(b, "building_costs",
"building_id", "resource_costs", "resource_id", "base_amount")

Dashboard edit → WS push → SDK mutates b.resource_costs in-place → done. No further code needed for the data flow.

What the SDK eliminates:

TaskLOC without SDK
HTTP fetch + auth + retry~30
JSON parse + type coercion~20
Disk cache + offline fallback~40
WebSocket poll loop + reconnect~50
Row → resource.set() mapping per field~10 per table
Pivot aggregation (rows → dict)~15 per dict property
Change detection + signal emit~20
Total~185–230 LOC

6 lines of game code replace ~185–230 LOC of infrastructure.

For the full integration guide including UI reactivity, the queue_free trap, and a reusable BalancingRefresh helper, see the Live Balancing Cookbook.

  1. Go to Live Ops > Balancing
  2. Click New Table and enter a name (e.g., “XP_PROGRESSION”)
  3. Define columns: level, xp_required, reward_amount
  4. Add rows with data
  5. Click Save

The table is immediately available via the Remote Config API.

Edit cells directly in the spreadsheet. Changes are saved to a draft version until published.

Import existing balance data:

  1. Click Import CSV on a table
  2. Select a CSV file (must match column headers)
  3. Review the preview
  4. Click Merge to replace current data

Every published version is preserved:

ActionDescription
PreviewSee what a past version contained
CompareShow diff between two versions
RollbackRevert to a previous version
level,xp_required,reward_coins,reward_gems
1,0,0,0
2,100,50,1
3,250,100,2
4,450,150,3
5,700,200,5

Query this from your game:

var xp_table = await QuestData.get_game_data("XP_PROGRESSION")
var level_2_xp = xp_table[1]["xp_required"] # 100
  • Draft mode: Multiple editors can work on the same table
  • Publishing: Click Publish to make it available to games
  • Audit Log: See who changed what and when
Terminal window
# Get a table
curl "https://api.questdata.io/v1/gamedata/XP_PROGRESSION" \
-H "x-game-api-key: YOUR_API_KEY"
# Get a specific version
curl "https://api.questdata.io/v1/gamedata/XP_PROGRESSION?version=5" \
-H "x-game-api-key: YOUR_API_KEY"

Response:

{
"table": "XP_PROGRESSION",
"version": 5,
"published_at": "2026-04-06T10:30:00Z",
"columns": ["level", "xp_required", "reward_coins"],
"rows": [
{"level": 1, "xp_required": 0, "reward_coins": 0},
{"level": 2, "xp_required": 100, "reward_coins": 50}
]
}