platforms/devplace/code_farm_api.md

DevPlace Code Farm Game API

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.

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.

GET /game - Code Farm page

The player's own farm: HUD, plot grid, shop, and leaderboard.

Minimal role: Member

Sample response

{
  "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 autoharvested/autoharvestcoins/autoharvest_xp) and charges any due Defense upkeep.

Minimal role: Member

Sample response

{
  "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), timetokernel, fair_play, or era (current Era only, empty when none is running). Cached about 15 seconds.

Minimal role: Public

Parameters

NameInTypeRequiredDescription
boardquerystringnoLeaderboard board key.

Sample response

{
  "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 canwater/cansteal flags computed for the viewer.

Minimal role: Public

Parameters

NameInTypeRequiredDescription
usernamepathstringyesFarm owner's username.

Sample response

{
  "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

NameInTypeRequiredDescription
slotformintegeryesPlot slot index, 0-based.
cropformstringyesCrop key.

Sample response

{
  "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

NameInTypeRequiredDescription
slotformintegeryesPlot slot index, 0-based.

Sample response

{
  "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 nextplotcost.

Minimal role: Member

Sample response

{
  "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 cinextcost.

Minimal role: Member

Sample response

{
  "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

NameInTypeRequiredDescription
usernamepathstringyesFarm owner's username.
slotformintegeryesPlot slot index, 0-based.

Sample response

{
  "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 stealcoins field is the exact payout) and the owner keeps and can still harvest the remainder; the plot records the share taken as raidedfraction. 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

NameInTypeRequiredDescription
usernamepathstringyesFarm owner's username.
slotformintegeryesPlot slot index, 0-based.

Sample response

{
  "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

NameInTypeRequiredDescription
slotformintegeryesPlot slot index, 0-based.

Sample response

{
  "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 dailystreakreset flag and daily_reward already reflect that.

Minimal role: Member

Sample response

{
  "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

NameInTypeRequiredDescription
perkformstringyesPerk key.

Sample response

{
  "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

NameInTypeRequiredDescription
questformstringyesQuest kind.
scopeformstringnodaily (default) or weekly.

Sample response

{
  "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

{
  "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

{
  "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

NameInTypeRequiredDescription
keyformstringyesLegacy upgrade key.

Sample response

{
  "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

NameInTypeRequiredDescription
keyformstringyesMastery upgrade key.

Sample response

{
  "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

NameInTypeRequiredDescription
keyformstringyesInfrastructure key.

Sample response

{
  "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 defensenextcost 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

{
  "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 defensedowngradeavailable is true in the farm state.

Minimal role: Member

Sample response

{
  "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

NameInTypeRequiredDescription
keyformstringyesCosmetic key.

Sample response

{
  "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

NameInTypeRequiredDescription
keyformstringyesAn owned title cosmetic key.

Sample response

{
  "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.

Endpoints

MethodPathPurpose
GET/gameYour farm page (HTML, or the same JSON as /game/state when asked).
GET/game/stateYour full farm state (always JSON).
GET/game/leaderboardTop farms (public). Accepts ?board=.
GET/game/farm/{username}Another member's farm.
POST/game/plantPlant crop in slot.
POST/game/harvestHarvest the build in slot.
POST/game/fertilizeHalve the remaining time of slot.
POST/game/buy-plotUnlock one more plot.
POST/game/upgradeRaise the CI tier.
POST/game/perkUpgrade perk (yield, growth, discount, xp).
POST/game/dailyClaim the daily bonus.
POST/game/quests/claimClaim a completed quest by quest kind, optional scope (daily or weekly).
POST/game/prestigeRefactor at level 10 or above; costs the current refactor_cost in coins.
POST/game/grantClaim the weekly community grant from the treasury.
POST/game/legacyBuy a Legacy upgrade (key) with Stars.
POST/game/masteryBuy a Mastery upgrade (key) with Mastery points.
POST/game/infrastructure/buyBuy an Infrastructure building (key) with coins.
POST/game/defense/upgradeBuy the next Defense tier with coins.
POST/game/defense/downgradeDrop one Defense tier to escape its upkeep (no refund).
POST/game/cosmetics/buyBuy a cosmetic (key) with coins.
POST/game/cosmetics/equipEquip an owned title cosmetic (key).
POST/game/farm/{username}/waterWater a neighbour's build in slot.
POST/game/farm/{username}/stealRaid 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:

{"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

import json, urllib.request

request = urllib.request.Request(
    "https://devplace.net/game/state",
    headers={"X-API-KEY": "<your-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:

{
  "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. rewardcoins/rewardxp 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, rewardcoins, rewardxp, growseconds, minlevel, 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: ownerusername, owneruid, is_owner.

Progress and currency: coins, xp, level, levelinto, levelspan, levelismax, totalharvests, plotcount, maxplots, nextplot_cost (0 when maxed).

CI: citier, cilabel, cispeed, cinexttier, cinextlabel, cinext_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, prestigemultiplier, prestigeminlevel, prestigeavailable (owner), refactorcost, refactoraffordable (owner), refactorcarryoverpct, refactorcarryoverpreview, stars.

Grant and treasury (owner): grantavailable, grantamount, grantreason, treasurybalance.

Daily: streak, dailyavailable (owner), dailystreakreset (true when your streak lapsed, so dailyreward already reflects the reset value), daily_reward.

Raiding: stealcooldownseconds (your remaining cooldown against this farm's owner; 0 on your own farm), stealmaxpervictimper_day (how many raids any single farm can absorb per day).

Mastery and lifetime stats: masterypoints, masterypointsearnedtotal, masteryanalyticsunlocked, lifetimecoinsearned, lifetimeharvests, harvestsweek.

Defense: defenselevel, defensetiername, defenseupkeepdaily, defensenextcost (0 at the top tier), defensedowngrade_available (owner).

Cosmetics and boosts: activetitle, underdogboostsecondsremaining, contractboostseconds_remaining.

Auto-harvest (owner): autoharvested, autoharvestcoins, autoharvest_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: eraactive, eraname, eracoins, eraharvests.

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.

#!/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 canwater is true, raid where cansteal 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.