🀝Economies - UGC

Welcome to the UGC layer of Sunflower Land. This is not only cosmetics: players can launch resources, complex gameplay loops, and more through the resource launchpad and economy editor.

  • This feature is experimental. Enable it in the game: Settings β†’ Developer Options β†’ Experiments β†’ Economy Editor.

  • With the economy editor enabled, you can also browse other players’ economies and games from Marketplace β†’ Economies.

This document focuses on HTTP APIs used by hosted HTML minigames. Handler code in this repo lives under src/api/minigames/ (session + actions) and is wired in infra/api.ts as the Minigames API Gateway (see MinigamesApi routes for /data, /action, /animate/..., /bumpkins/metadata/...).


Setting up an economy

An economy is your tokenised design: resources, rules, and copy that define what players can hold and do. You can keep it minimal or build something closer to a world builder.

Items

Here you define the things that make up your game: resources, buildings, achievements, skills, scores, etc. Think in terms of tokenising everythingβ€”each distinct thing players earn, spend, or unlock should usually be an item (balance token key) with metadata (name, description, optional art, marketplace fields).

Rules

Rules describe allowed transitions on player balances (and timed generator jobs).

Rule type (editor)
Purpose

Shop

Burn some tokens, mint others (and optional require / caps). Use for crafting, shops, exchanges (e.g. burn 3 wood, mint an axe). Shop-derived rows can appear in the default economy dashboard when showInShop is not false.

Generator

Like a shop, but includes time and optional random collect outcomes (chance on collect rows). Use for cooking, production, staking-style β€œcome back later” loops. Often modelled as one action with produce + collect and itemId for the active job.

Custom

Rules for advanced / iframe minigames. They are not shown in the basic economy dashboard; your game calls them by action id via the API.

Every time you save, your economy config is published for players. For behaviour that cannot be expressed in rules alone (dungeons, battles, etc.), host a custom minigame and call custom actions from your client.

Server-side rule shapes and processing align with src/domain/playerEconomy/types.ts and processAction.ts.


Building a custom portal & uploading

Custom minigames are static HTML experiences opened in the browser (often in an iframe). The official templates use React and Phaser, but you may use any stack.

  • Ship a build with index.html at the entry URL.

  • In the economy editor, use the upload flow to publish the files needed to run your game.

Reading and writing player data

  • Read economy config + farm snapshot + per-player economy state: Minigames API GET /data?type=session (see below). Use the portal JWT in Authorization.

  • Write state transitions that you defined as rules: Minigames API POST /action with type: "minigame.action" (see below).

Reference implementation (open source)

  • Template repo (React + portal bootstrap): sunflower-land-template

    • JWT from query string: src/lib/portal/url.ts (getJwt, optional minigamesApiUrl / apiUrl query params).

    • Session fetch: src/lib/portal/api.ts (getPlayerEconomySession).

    • Action POST: same file (postPlayerEconomyAction).

    • Economy dashboard example: src/examples/ui-resources/ (shop + generator UI driven by session payload).


Authentication (portal JWT)

Before you can load session data or submit actions, you need a portal JWT. It identifies the player and farm and authorises Minigames API calls. The portal id inside the JWT must match your economy’s slug as saved in the editor.

In production (player opens your game)

The game client typically opens your hosted URL with the token in the query string, for example:

https://your-economy.minigames.sunflower-land.com/?jwt=…

Read jwt in your app and send it on every Minigames request:

Local development

In the economy editor, use Generate token (or equivalent) and append the token to your dev server URL, e.g.:

http://localhost:3000/?jwt=…

Server validation

Handlers verify the JWT with the portal secret; see src/api/minigames/data.ts and src/api/minigames/action.ts.


Economy data (session payload)

The session response is the structured bundle your minigame uses to render UI and validate client-side optimistically:

  • farm β€” high-level farm info (e.g. SFL balance string, bumpkin) for context.

  • playerEconomy β€” balances, active generator jobs (generating), activity counters, daily mint buckets, optional dailyActionUses / purchaseCounts.

  • actions β€” map of action id β†’ rule definition (shop / generator / custom shapes).

  • items β€” optional map of token key β†’ display metadata (name, description, image, marketplace id / tradeable, etc.).

  • descriptions, visualTheme, mainCurrencyToken β€” optional chrome for dashboards.

  • playUrl β€” canonical hosted game base for this portal (derived server-side; see playerEconomyOperations.ts).

Authoritative TypeScript types: PlayerEconomySessionPayload.

Example GET /data?type=session success body

Shape returned by the API (your real actions / items / balances will differ):

Session errors (selected)

HTTP
Meaning

401

Missing / invalid JWT.

422 + errorCode: "UNKNOWN_PLAYER_ECONOMY"

No saved economy for this portal id, or slug mismatch vs editor.

422 + errorCode: "FARM_NOT_FOUND"

JWT farmId does not match a farm in this API environment.

403

Token minigames / player economies not available for this farm (feature gating).


Loading session data

Request

  • Implementation: src/api/minigames/data.handler β†’ minigameSessionData β†’ loadPlayerEconomySession.

  • Portal id is taken only from the JWT (not from query params).

Base URL

The Minigames API is deployed as its own API Gateway; the exact hostname depends on environment (there is not a single guaranteed public host like minigame-api.sunflower-land.com in codeβ€”always use the base URL from your deployment or client config, e.g. VITE_MINIGAMES_API_URL in the template). Hosted game sites often follow {slug}.minigames.sunflower-land.com (see MINIGAMES_SITE_HOST_SUFFIX in infra/api.ts); the API origin for fetch may differβ€”point your client at the Minigames API base you were given.

Example client

See sunflower-land-template getPlayerEconomySession.


Actions (mutations)

Use actions when the player collects something, starts a run, submits a score, unlocks progression, etc. The server only executes actions that exist in your published economy config, which keeps outcomes bounded to what you defined.

Request

Body (JSON)

Field
Required
Description

type

Yes

Must be "minigame.action".

action

Yes

Action id from the editor (set a readable custom id in the label section when possible).

itemId

No

For generator collect (and similar), the job id returned when the job was started (or present in playerEconomy.generating).

amounts

No

Integer map used for ranged mint / ranged burn rules: token key β†’ chosen amount within your configured min/max.

Success response

collectGrants appears when the server resolves weighted collect outcomes for a collect action.

Errors

HTTP
Typical cause

400

Invalid body, unknown action, rule validation failed (error message in body).

401

Invalid JWT.

422

Unknown economy / farm (same ideas as session).

403

Feature disabled for farm.

Implementation: src/api/minigames/action.handler, minigameAction.ts, executePlayerEconomyAction.

Example client

sunflower-land-template postPlayerEconomyAction.


Other useful APIs & data

Bumpkin / NPC animations (Minigames API)

Route (same API Gateway as /data and /action):

Renders bumpkin (and related) sprite animations for NPCs and large character art. Handler: src/api/animation/. Dependencies include layer definitions under src/domain/bumpkins/ (e.g. layerImages, npcBuilder, bumpkinBuilder). Use this when you need walking, fishing, mining, chopping, jumping, etc., driven by bumpkin tokenUri and animation name.

There is also GET /bumpkins/metadata/{tokenUri} on the same API for metadata helpers.

Marketplace: discovering economies & trade context (main Sunflower Land API)

Browsing Marketplace β†’ Economies in the game uses the main game API (player session JWT, not the portal JWT), for example:

Returns economy rows and related leaderboard-style data; see loadEconomiesMarketplacePageData and the client helper loadEconomiesMarketplaceData.ts in the sunflower-land repo.

For a specific tradable (listings, offers, sale history) the game uses collection endpoints such as:

See loadTradeable.ts. Use this pattern when building dashboards or tools that need market history for an economy tokenβ€”not for mutating minigame state (that remains POST /action on the Minigames API).


Quick reference

Goal
API
Auth

Load config + economy state for minigame

GET /data?type=session

Portal JWT

Apply a defined rule

POST /action (type: "minigame.action")

Portal JWT

NPC / bumpkin animation asset

GET /animate/{tokenUri}/{animation}

Per deployment (often public GET)

List economies in marketplace

GET /data?type=marketplaceEconomies

Game user JWT

Tradeable detail / history

GET /collection/...

Game user JWT

For infrastructure wiring (routes, CORS, memory), see MinigamesApi in infra/api.ts.

Last updated