--- title: "DevPlace Code Farm Game API" description: "The Code Farm endpoints: reading state and leaderboards, planting and harvesting, plots and upgrades, watering and raiding a neighbour, fertilizer, daily bonus, quests, perks, prestige, mastery, legacy and the infrastructure, defense and cosmetic sinks." language: null framework: null category: api_design tags: - devplace - api - http-api - game-api - code-farm - rest - state-machine - leaderboard - automation - bots keywords: - devplace GET /game/state json - devplace POST /game/plant harvest endpoints - devplace game water steal neighbour api - devplace game prestige mastery legacy endpoints - devplace code farm bot script api last_updated: 2026-08-12 difficulty: intermediate version: "DevPlace (devplace.net), documented 2026-08" related: - README.md - authentication.md - conventions_and_errors.md search_priority: normal status: published --- # DevPlace Code Farm Game API ## Endpoint reference The Code Farm is a cooperative idle game. Each member owns a farm of plots, plants software projects that build over real time, harvests them for coins and XP, upgrades their CI tier for faster builds, and waters other members' growing builds to speed them up and earn coins. Refactoring (prestige) costs a dynamic coin fee that grows with prestige and current wealth; the fees fill a community treasury from which active low-balance farms can claim a weekly grant. All endpoints negotiate HTML or JSON. POST bodies are form encoded (`application/x-www-form-urlencoded`). Every own-farm action returns `{"ok": true, "farm": {...}}` - the full updated farm state - so a client can refresh without a second request; the two neighbour actions (water, steal) return the neighbour's farm as `{"farm": {...}}`, and a successful steal adds `stole_coins`. An invalid action (not enough coins, wrong plot state, a protected harvest, an active cooldown) returns HTTP 400 as `{"error": {"status": 400, "message": "..."}}`; an unknown farm username is 404. Reading your own farm state also runs lazy owner effects: the CI Bot legacy upgrade auto-harvests ready builds, and any due Defense upkeep is charged. The complete rules, formulas, and an automated client are on the [Code Farm guide](#playing-through-the-api). ### `GET /game` - Code Farm page The player's own farm: HUD, plot grid, shop, and leaderboard. *Minimal role:* Member **Sample response** ```json { "ok": true, "farm": { "coins": 50, "level": 1, "plots": [] } } ``` ### `GET /game/state` - Farm state The signed-in player's full farm state as JSON. Reading it auto-collects ready builds (with the CI Bot legacy upgrade, reported as auto_harvested/auto_harvest_coins/auto_harvest_xp) and charges any due Defense upkeep. *Minimal role:* Member **Sample response** ```json { "ok": true, "farm": { "coins": 50, "level": 1, "ci_tier": 1, "plot_count": 4, "prestige": 0, "stars": 0, "refactor_cost": 20000, "plots": [ { "slot": 0, "state": "empty", "raided_fraction": 0.0 } ], "daily_streak_reset": false, "contract_boost_seconds_remaining": 0, "auto_harvested": 0, "steal_max_per_victim_per_day": 3, "defense_downgrade_available": false, "crops": [ { "key": "python", "name": "Python Script", "cost": 15, "reward_coins": 36, "grow_seconds": 120, "locked": false, "market_state": "normal" } ] } } ``` ### `GET /game/leaderboard` - Farm leaderboard Top 25 farmers on a chosen board: score (default), prestige, harvests (this week), raids (avg coins per successful raid over 30 days, min 3 raids), time_to_kernel, fair_play, or era (current Era only, empty when none is running). Cached about 15 seconds. *Minimal role:* Public **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `board` | query | string | no | Leaderboard board key. | **Sample response** ```json { "entries": [ { "rank": 1, "username": "alice", "level": 4, "xp": 600, "coins": 240, "total_harvests": 52, "prestige": 1, "score": 6120, "title": "The Architect" } ] } ``` ### `GET /game/farm/{username}` - View a farm Another player's farm, with per-plot can_water/can_steal flags computed for the viewer. *Minimal role:* Public **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `username` | path | string | yes | Farm owner's username. | **Sample response** ```json { "farm": { "owner_username": "alice", "is_owner": false, "plots": [] } } ``` ### `POST /game/plant` - Plant a crop Plant a crop in an empty plot. Costs the crop's live coin price (the cost field in the farm state's crops list). *Minimal role:* Member **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `slot` | form | integer | yes | Plot slot index, 0-based. | | `crop` | form | string | yes | Crop key. | **Sample response** ```json { "ok": true, "farm": { "coins": 35 } } ``` ### `POST /game/harvest` - Harvest a build Harvest a finished (state ready) build for coins and XP. *Minimal role:* Member **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `slot` | form | integer | yes | Plot slot index, 0-based. | **Sample response** ```json { "ok": true, "farm": { "coins": 86 } } ``` ### `POST /game/buy-plot` - Buy a plot Unlock a new plot (up to 12). Cost starts at 100 coins and doubles per extra plot; the exact price is the farm state's next_plot_cost. *Minimal role:* Member **Sample response** ```json { "ok": true, "farm": { "plot_count": 5 } } ``` ### `POST /game/upgrade` - Upgrade CI Upgrade the farm CI tier for faster builds (up to tier 5); the exact price is the farm state's ci_next_cost. *Minimal role:* Member **Sample response** ```json { "ok": true, "farm": { "ci_tier": 2 } } ``` ### `POST /game/farm/{username}/water` - Water a build Water another player's growing build to cut 8% off its build time; pays the visitor 6 coins scaled by their own prestige and Tech Debt Payoff multiplier, plus 3 XP. Once per visitor per build, 3 waterings per build total. *Minimal role:* Member **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `username` | path | string | yes | Farm owner's username. | | `slot` | form | integer | yes | Plot slot index, 0-based. | **Sample response** ```json { "farm": { "owner_username": "alice" } } ``` ### `POST /game/farm/{username}/steal` - Steal a build Raid another player's ready build once its protection window has passed. You take a share of the build's realized coin value (half by default, less against defended owners - the plot's steal_coins field is the exact payout) and the owner keeps and can still harvest the remainder; the plot records the share taken as raided_fraction. Limited to once per hour per neighbour and 3 raids per victim per day; a fully stripped build reports steal_reason stripped, and Security Fortress builds are immune. *Minimal role:* Member **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `username` | path | string | yes | Farm owner's username. | | `slot` | form | integer | yes | Plot slot index, 0-based. | **Sample response** ```json { "farm": { "owner_username": "alice" }, "stole_coins": 18 } ``` ### `POST /game/fertilize` - Fertilize a build Spend coins to halve a growing build's remaining time (the plot's fertilize_cost field is the exact price). The price is computed from the exact value this build will pay out - including the golden multiplier and any active contract, Underdog, or Canary upside - so fertilizing is a pure time-skip and never a profit, on any build, at any prestige, with any combination of boosts. *Minimal role:* Member **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `slot` | form | integer | yes | Plot slot index, 0-based. | **Sample response** ```json { "ok": true, "farm": { "coins": 12 } } ``` ### `POST /game/daily` - Claim daily bonus Claim the once-per-UTC-day coin bonus; consecutive days grow a streak (20 coins on day one up to 92 from day seven on), scaled by your own prestige and Tech Debt Payoff multiplier. A lapsed streak resets to day one - the farm state's daily_streak_reset flag and daily_reward already reflect that. *Minimal role:* Member **Sample response** ```json { "ok": true, "farm": { "streak": 3, "coins": 94 } } ``` ### `POST /game/perk` - Upgrade a perk Upgrade a permanent perk with coins: yield (+5% harvest coins), growth (+4% build speed), discount (-3% planting cost), or xp (+5% harvest XP) per level. Perks reset on refactor. *Minimal role:* Member **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `perk` | form | string | yes | Perk key. | **Sample response** ```json { "ok": true, "farm": { "coins": 0 } } ``` ### `POST /game/quests/claim` - Claim a quest Claim a completed daily quest by its kind, or (with scope=weekly, requires the Legacy Contracts Mastery upgrade) the weekly contract, which pays Stars plus a 48-hour +20% coin boost instead of coins. *Minimal role:* Member **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `quest` | form | string | yes | Quest kind. | | `scope` | form | string | no | daily (default) or weekly. | **Sample response** ```json { "ok": true, "farm": { "coins": 130 } } ``` ### `POST /game/prestige` - Refactor (prestige) Reset the farm at level 10+ for a permanent +25% coin bonus and earn Stars to spend on Legacy upgrades. Refactoring costs a coin fee that scales with prestige and current wealth (the farm state's refactor_cost); the fee funds the community treasury and a fraction of the remaining coins (10% base, up to 35% with the Golden Parachute Legacy upgrade) carries over. From prestige 50 onward, every 10 more prestige also earns a permanent Mastery point. *Minimal role:* Member **Sample response** ```json { "ok": true, "farm": { "prestige": 1, "coins": 6550 } } ``` ### `POST /game/grant` - Claim the community grant Claim the weekly community grant, paid from the treasury filled by refactor fees and divided between everyone currently eligible (capped at 2500 coins, suppressed below 250). Eligible farms are active (5+ harvests this week), below 10000 coins, and at most prestige 5. *Minimal role:* Member **Sample response** ```json { "ok": true, "farm": { "coins": 2550 } } ``` ### `POST /game/legacy` - Buy a Legacy upgrade Spend Stars on a permanent Legacy upgrade that survives every refactor: autoharvest (CI Bot), multiplier (+10% coins/level), speed (+5% build speed/level), plots (+1 starting plot/level), defense (+30s grace, -5% steal loss/level), or carryover (Golden Parachute, +5% refactor carry-over/level). *Minimal role:* Member **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `key` | form | string | yes | Legacy upgrade key. | **Sample response** ```json { "ok": true, "farm": { "stars": 1 } } ``` ### `POST /game/mastery` - Buy a Mastery upgrade Spend Mastery points (earned at prestige 50 and every 5 prestige after) on a permanent Mastery upgrade: autoreplant (Continuous Delivery, 3 points), analytics (Farm Analytics, 2 points), or contracts (Legacy Contracts, 4 points). *Minimal role:* Member **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `key` | form | string | yes | Mastery upgrade key. | **Sample response** ```json { "ok": true, "farm": { "mastery_points": 0 } } ``` ### `POST /game/infrastructure/buy` - Buy Infrastructure Buy a permanent, expensive, prestige-gated Infrastructure building: registry (Rust/Compiler/Kernel build 15% faster; 3M coins, prestige 3), canary (12% chance to double a harvest, 6% to only refund its planting cost; 6M, prestige 8), or observability (caps what any raider can take from you at 20% of a build's value; 15M, prestige 15). *Minimal role:* Member **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `key` | form | string | yes | Infrastructure key. | **Sample response** ```json { "ok": true, "farm": { "coins": 0 } } ``` ### `POST /game/defense/upgrade` - Upgrade Defense Buy the next Defense tier (Firewall through Zero Trust Mesh; the farm state's defense_next_cost is the exact price). Each tier multiplicatively reduces what a raider takes from you and adds steal grace, but adds an ongoing daily coin upkeep of max(tier minimum, 0.2% of your balance). If you cannot pay, the tier decays by one level and only what you can afford is taken - your balance is never emptied. *Minimal role:* Member **Sample response** ```json { "ok": true, "farm": { "defense_level": 1 } } ``` ### `POST /game/defense/downgrade` - Downgrade Defense Drop your Defense down one tier to escape its daily upkeep. There is no refund. Available whenever defense_downgrade_available is true in the farm state. *Minimal role:* Member **Sample response** ```json { "ok": true, "farm": { "defense_level": 0 } } ``` ### `POST /game/cosmetics/buy` - Buy a cosmetic Buy a purely cosmetic title or plot skin with coins. No gameplay effect. The farm state's cosmetics list carries each key, cost, and an owned flag. *Minimal role:* Member **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `key` | form | string | yes | Cosmetic key. | **Sample response** ```json { "ok": true, "farm": { "coins": 0 } } ``` ### `POST /game/cosmetics/equip` - Equip a title Equip an owned title cosmetic so its display name shows next to your name on the leaderboard. *Minimal role:* Member **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `key` | form | string | yes | An owned title cosmetic key. | **Sample response** ```json { "ok": true, "farm": { "active_title": "title_architect" } } ``` ## Playing through the API Every action is a normal DevPlace endpoint that negotiates HTML or JSON. Send `Accept: application/json` to get JSON, and authenticate exactly like the rest of the API: with your **API key** in an `X-API-KEY` header (or `Authorization: Bearer`). Your key is on your [profile page](https://devplace.net/profile/). ### Endpoints | Method | Path | Purpose | |--------|------|---------| | `GET` | `/game` | Your farm page (HTML, or the same JSON as `/game/state` when asked). | | `GET` | `/game/state` | Your full farm state (always JSON). | | `GET` | `/game/leaderboard` | Top farms (public). Accepts `?board=`. | | `GET` | `/game/farm/{username}` | Another member's farm. | | `POST` | `/game/plant` | Plant `crop` in `slot`. | | `POST` | `/game/harvest` | Harvest the build in `slot`. | | `POST` | `/game/fertilize` | Halve the remaining time of `slot`. | | `POST` | `/game/buy-plot` | Unlock one more plot. | | `POST` | `/game/upgrade` | Raise the CI tier. | | `POST` | `/game/perk` | Upgrade `perk` (`yield`, `growth`, `discount`, `xp`). | | `POST` | `/game/daily` | Claim the daily bonus. | | `POST` | `/game/quests/claim` | Claim a completed quest by `quest` kind, optional `scope` (`daily` or `weekly`). | | `POST` | `/game/prestige` | Refactor at level 10 or above; costs the current `refactor_cost` in coins. | | `POST` | `/game/grant` | Claim the weekly community grant from the treasury. | | `POST` | `/game/legacy` | Buy a Legacy upgrade (`key`) with Stars. | | `POST` | `/game/mastery` | Buy a Mastery upgrade (`key`) with Mastery points. | | `POST` | `/game/infrastructure/buy` | Buy an Infrastructure building (`key`) with coins. | | `POST` | `/game/defense/upgrade` | Buy the next Defense tier with coins. | | `POST` | `/game/defense/downgrade` | Drop one Defense tier to escape its upkeep (no refund). | | `POST` | `/game/cosmetics/buy` | Buy a cosmetic (`key`) with coins. | | `POST` | `/game/cosmetics/equip` | Equip an owned title cosmetic (`key`). | | `POST` | `/game/farm/{username}/water` | Water a neighbour's build in `slot`. | | `POST` | `/game/farm/{username}/steal` | Raid a neighbour's unprotected ready build in `slot`. | POST bodies are form encoded (`application/x-www-form-urlencoded`). Form fields are `slot` (an integer plot index, 0-based), `crop`, `perk`, `quest`, `scope`, and `key` (a Legacy/Mastery/Infrastructure/cosmetic key) where the table notes them. Every own-farm POST returns `{"ok": true, "farm": {...}}` - the full updated farm - so one call both performs the action and gives you the new state. The two neighbour actions return the **neighbour's** farm as you see it (`{"farm": {...}}`), and a successful steal adds `"stole_coins"` with your payout. ### Errors An invalid action (not enough coins, wrong plot state, a still-protected harvest, an active cooldown, an unmet requirement) returns **HTTP 400** with a human-readable reason: ```json {"error": {"status": 400, "message": "Not enough coins to plant that."}} ``` An unknown farm username is **404**. Invalid credentials are **401**; a request with no credentials at all is redirected (303) to the login page, so always send your API key. Mutating requests count against the sitewide rate limit (per client IP, 60 per minute by default) - reads do not. ### Two things that happen on state reads Loading your own farm (`GET /game`, `GET /game/state`, or the farm returned by any action) is when lazy owner-side effects run, so a scripted client should expect them: - With the **CI Bot** Legacy upgrade, every ready build is auto-harvested (and with Continuous Delivery, auto-replanted) during the read - the state you get back is post-collection. - With a **Defense** building, any daily upkeep due is charged during the read, so your `coins` can be lower than the previous response predicted (and the tier one lower, if you could not pay). ### Reading the state ```python import json, urllib.request request = urllib.request.Request( "https://devplace.net/game/state", headers={"X-API-KEY": "", "Accept": "application/json"}, ) with urllib.request.urlopen(request) as response: farm = json.loads(response.read())["farm"] print("coins", farm["coins"], "level", farm["level"], "plots", farm["plot_count"]) for plot in farm["plots"]: print(plot["slot"], plot["state"], plot.get("crop_name"), plot.get("remaining_seconds")) ``` ### The plot shape `GET /game/state` returns `{"ok": true, "farm": {...}}`. The farm carries your totals plus the lists you act on. A plot looks like this: ```json { "slot": 0, "state": "growing", "crop_key": "python", "crop_name": "Python Script", "crop_icon": "🐍", "reward_coins": 36, "reward_xp": 5, "ready_at": "2026-06-23T12:34:56+00:00", "remaining_seconds": 73, "watered_count": 1, "max_waters": 3, "can_water": false, "can_steal": false, "steal_coins": 0, "steal_cooldown_seconds": 0, "steal_reason": "", "is_golden": false, "fertilize_cost": 22, "raided_fraction": 0.0, "raided_pct": 0 } ``` A plot's `state` is `empty`, `growing`, or `ready`. `reward_coins`/`reward_xp` on a plot are the crop's **base** rewards; the multiplied live values are on the matching entry in `crops`. An entry in `crops` carries the live `cost`, `reward_coins`, `reward_xp`, `grow_seconds`, `min_level`, `market_state`, and a `locked` flag, so a client can decide what is both unlocked and affordable without hard-coding the tables above. ### The farm state reference Every field on the `farm` object, grouped. Fields marked *(owner)* are only populated when you read your **own** farm - on someone else's farm the lists are empty and the flags false/zero. **Identity:** `owner_username`, `owner_uid`, `is_owner`. **Progress and currency:** `coins`, `xp`, `level`, `level_into`, `level_span`, `level_is_max`, `total_harvests`, `plot_count`, `max_plots`, `next_plot_cost` (0 when maxed). **CI:** `ci_tier`, `ci_label`, `ci_speed`, `ci_next_tier`, `ci_next_label`, `ci_next_cost` (all `next` fields 0/empty at the top tier). **Lists:** `plots`, `crops`, plus *(owner)* `perks`, `quests` (daily entries, and the weekly contract when unlocked), `legacy`, `mastery`, `infrastructure`, `cosmetics`. Each purchasable entry carries `key`, `name`, `icon`, `description`, its current `level`/`owned` state, the exact next `cost`, and a `maxed` flag where applicable. **Refactor:** `prestige`, `prestige_multiplier`, `prestige_min_level`, `prestige_available` *(owner)*, `refactor_cost`, `refactor_affordable` *(owner)*, `refactor_carryover_pct`, `refactor_carryover_preview`, `stars`. **Grant and treasury** *(owner)*: `grant_available`, `grant_amount`, `grant_reason`, `treasury_balance`. **Daily:** `streak`, `daily_available` *(owner)*, `daily_streak_reset` (true when your streak lapsed, so `daily_reward` already reflects the reset value), `daily_reward`. **Raiding:** `steal_cooldown_seconds` (your remaining cooldown against this farm's owner; 0 on your own farm), `steal_max_per_victim_per_day` (how many raids any single farm can absorb per day). **Mastery and lifetime stats:** `mastery_points`, `mastery_points_earned_total`, `mastery_analytics_unlocked`, `lifetime_coins_earned`, `lifetime_harvests`, `harvests_week`. **Defense:** `defense_level`, `defense_tier_name`, `defense_upkeep_daily`, `defense_next_cost` (0 at the top tier), `defense_downgrade_available` *(owner)*. **Cosmetics and boosts:** `active_title`, `underdog_boost_seconds_remaining`, `contract_boost_seconds_remaining`. **Auto-harvest** *(owner)*: `auto_harvested`, `auto_harvest_coins`, `auto_harvest_xp` - what the CI Bot collected during this read, so a client can report it. They are 0 unless the CI Bot Legacy upgrade is owned and something was ready. **Era:** `era_active`, `era_name`, `era_coins`, `era_harvests`. ### A complete automated farmer This script plays the core loop on a schedule: it claims the daily bonus and any finished quests, harvests every ready build, replants empty plots with the most valuable crop it can afford, and prints a one-line summary. It uses only the Python standard library. Set your URL and API key, then run it under `cron` or a `systemd` timer, or leave it looping. ```python #!/usr/bin/env python3 """Plays the DevPlace Code Farm automatically over the JSON API.""" import json import time import urllib.error import urllib.parse import urllib.request BASE = "https://devplace.net" API_KEY = "63995001-2291-45bf-9fe3-45dae21cfcee" POLL_SECONDS = 60 def call(method, path, fields=None): headers = {"X-API-KEY": API_KEY, "Accept": "application/json"} data = None if fields is not None: data = urllib.parse.urlencode(fields).encode() headers["Content-Type"] = "application/x-www-form-urlencoded" request = urllib.request.Request(BASE + path, data=data, headers=headers, method=method) with urllib.request.urlopen(request) as response: return json.loads(response.read()) def state(): return call("GET", "/game/state")["farm"] def best_affordable_crop(farm): options = [c for c in farm["crops"] if not c["locked"] and c["cost"] <= farm["coins"]] if not options: return None return max(options, key=lambda c: c["reward_coins"]) def claim_free_rewards(farm): if farm.get("daily_available"): call("POST", "/game/daily") if farm.get("grant_available"): call("POST", "/game/grant") for quest in farm.get("quests", []): if quest.get("can_claim"): call("POST", "/game/quests/claim", {"quest": quest["kind"], "scope": quest["scope"]}) def harvest_and_replant(farm): for plot in farm["plots"]: if plot["state"] == "ready": call("POST", "/game/harvest", {"slot": plot["slot"]}) farm = state() for plot in farm["plots"]: if plot["state"] != "empty": continue crop = best_affordable_crop(farm) if not crop: break call("POST", "/game/plant", {"slot": plot["slot"], "crop": crop["key"]}) farm = state() return farm def run(): print("Code Farm automation started.") while True: try: farm = state() claim_free_rewards(farm) farm = harvest_and_replant(state()) print(f"coins={farm['coins']} level={farm['level']} harvests={farm['total_harvests']}") except urllib.error.HTTPError as error: print("api error:", error.code, error.read().decode()[:200]) except OSError as error: print("network error, retrying:", error) time.sleep(POLL_SECONDS) if __name__ == "__main__": run() ``` From here the natural extensions are easy: spend surplus coins with `POST /game/buy-plot` and `POST /game/upgrade` when you can afford them, raise perks with `POST /game/perk`, water neighbours by walking `GET /game/farm/{username}` and posting to its `/water` path for plots where `can_water` is true, raid where `can_steal` is true, and refactor with `POST /game/prestige` once `refactor_affordable` is set. Be polite to the rate limiter: mutating calls are limited per client, so a poll interval of a minute or more with one action per finished build stays well within limits.