🌱 How to Farm

Learn how to grow your skills at HappyHarvest.fun

🌾 Farm Overview

HappyHarvest.fun is designed to teach you how to work with JWT authentication, API rate limiting, and proper client-server communication. Your goal is to write a farming script that maintains a high water collection score by correctly calling our API endpoints.

💧 Water Collection Rules

  • Call /collect once every 30 seconds to collect 1 water
  • JWT tokens expire every 5 minutes - you must refresh them
  • Multiple calls within 30 seconds = water waste (water decreases by 10)
  • Miss a 30-second window without calling = 0 water for that window
  • Maximum water capacity: 1024
  • Claim land with 5 water, then expand your farming territory!
  • Land expansions get increasingly expensive - invest wisely!
  • Plant crops with water (costs have tripled!) - but they grow 3x faster!
  • Maintain perfect timing to maximize your water collection - it's more critical than ever!

🔄 Farm Flow

1

🚜 Register Farmer

Call /register with your farmer name to get unique API credentials (client_id and client_secret).

2

🔑 Get JWT Token

Use your credentials to call /auth/token and receive a JWT token that expires in 5 minutes.

3

💧 Collect Water

Call /collect with your JWT token once every 30 seconds to collect water. Time it perfectly!

4

🏞️ Claim Land

Once you have 5 water, claim your first plot of land with /claimLand to start your farming empire!

5

🏗️ Expand Territory

Use /expandLand to grow your farm from 1×1 to 32×32. Each expansion gets more expensive but gives you more land!

6

🌾 Plant Crops

Use /plant to plant crops on your land. Each crop costs water and has different grow times and market values!

7

🌟 Harvest for Credits

Wait for crops to mature, then use /harvest to collect credits. Monitor market prices for maximum profit!

8

⏰ Maintain Auth

Refresh your JWT token every 5 minutes and keep your water collection, planting, and harvesting loops running to climb the credits leaderboard.

🔌 API Endpoints

POST /register

Purpose: Register your farmer and get API credentials

⚠️ Important: One-Time Registration Only!

You can only call /register once with any farmer name to receive your credentials. If you call it again with the same name, you'll get an error and cannot retrieve your original credentials. Make sure to save your client_id and client_secret safely!

Body:

{ "playername": "your-farmer-name" }

Success Response:

{ "message": "Farmer registered successfully", "playername": "your-farmer-name", "client_id": "farmer-your-farmer-name-abc123", "client_secret": "secret-xyz789..." }

Error Response (duplicate name):

{ "error": "username_taken", "error_description": "This farmer name is already taken. Please choose a different name.", "suggestion": "Try adding numbers or other characters to make your farmer name unique." }
POST /auth/token

Purpose: Get a JWT access token (expires in 5 minutes)

Body:

{ "client_id": "your-client-id", "client_secret": "your-client-secret", "grant_type": "client_credentials" }

Response:

{ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 300 }
POST /collect

Purpose: Collect water for your farm (call once per 30 seconds)

Headers:

Authorization: Bearer <your-access-token>

Success Response:

{ "message": "Water collected successfully!", "playername": "your-farmer-name", "score": 42, "timestamp": "2023-12-05T10:30:00.000Z" }

Penalty Response (too frequent):

{ "message": "Water wasted! You tried to collect too early, the well needs time to refill...", "score": 32, "timeUntilNextAllowed": 45 }

Water Tank Full Response (at capacity):

{ "error": "water_tank_full", "error_description": "Your water tank is full! Maximum capacity is 1024 water.", "score": 1024, "maxWater": 1024 }
GET /profile

Purpose: View your farmer profile and stats

Headers:

Authorization: Bearer <your-access-token>

Response:

{ "playername": "your-farmer-name", "profile": { "github": "your-username", "twitter": "@your-handle", "ethereumAddress": "your.eth" }, "score": 42, "totalCalls": 45, "registeredAt": "2023-12-05T08:00:00.000Z", "lastActivity": "2023-12-05T10:30:00.000Z" }
POST /profile

Purpose: Update your farmer profile information

Headers:

Authorization: Bearer <your-access-token>

Body (all fields optional):

{ "github": "your-username-or-url", "twitter": "@your-handle-or-url", "ethereumAddress": "your.eth-or-0x1234..." }

Success Response:

{ "message": "Profile updated successfully!", "playername": "your-farmer-name", "profile": { "github": "your-username", "twitter": "@your-handle", "ethereumAddress": "farmer.eth" }, "timestamp": "2023-12-05T10:30:00.000Z" }
POST /claimLand

Purpose: Claim your first plot of farming land (costs 5 water)

Headers:

Authorization: Bearer <your-access-token>

Success Response:

{ "message": "Land claimed successfully! Your farming empire begins!", "playername": "your-farmer-name", "waterRemaining": 37, "landTiles": 1, "gridSize": 1, "expansionCost": 30 }

Error Response (insufficient water):

{ "error": "insufficient_water", "error_description": "You need 5 water to claim your first plot of land. You have 3 water.", "required": 5, "current": 3 }
POST /plant

Purpose: Plant crops on your claimed land (costs water)

Headers:

Authorization: Bearer <your-access-token> Content-Type: application/json

Body:

{ "cropType": "herb", "row": 0, "col": 0 }

Success Response:

{ "message": "Herb planted successfully! 🌱", "playername": "your-farmer-name", "crop": { "name": "Herb", "emoji": "🌿", "location": "(0,0)", "waterCost": 6, "matureIn": "0.11 hours", "matureAt": "2023-12-05T10:37:00.000Z", "expectedCredits": 0.5, "marketPrice": 0.5, "note": "Price may change before harvest!" }, "waterRemaining": 36, "creditsTotal": 0, "timestamp": "2023-12-05T10:30:00.000Z" }

Error Response (insufficient water):

{ "error": "insufficient_water", "error_description": "You need 6 water to plant Herb. You have 3 water.", "required": 6, "current": 3 }

Error Response (invalid coordinates):

{ "error": "invalid_coordinates", "error_description": "Invalid coordinates (5,5). Must be within your 2×2 land grid.", "validRange": "0-1" }
POST /harvest

Purpose: Harvest mature crops for credits

Headers:

Authorization: Bearer <your-access-token> Content-Type: application/json

Body:

{ "row": 0, "col": 0 }

Success Response:

{ "message": "Herb harvested successfully! 🌿", "playername": "your-farmer-name", "crop": { "name": "Herb", "emoji": "🌿", "location": "(0,0)", "creditsEarned": 0.52, "marketPrice": 0.52 }, "creditsTotal": 0.52, "waterRemaining": 36, "timestamp": "2023-12-05T10:37:00.000Z" }

Error Response (crop not mature):

{ "error": "crop_not_mature", "error_description": "Your Herb is not ready for harvest yet. Time remaining: 5 minutes.", "crop": "Herb", "timeRemainingMinutes": 5, "matureAt": "2023-12-05T10:35:00.000Z" }

Error Response (no crop found):

{ "error": "no_crop_found", "error_description": "No crop found at location (0,0).", "currentLandValue": 0 }
POST /expandLand

Purpose: Expand your farming territory (increasingly expensive)

Headers:

Authorization: Bearer <your-access-token>

Success Response:

{ "message": "Land expanded successfully! Your farm is now 2x2!", "playername": "your-farmer-name", "waterRemaining": 12, "landTiles": 4, "gridSize": 2, "expansionCost": 30, "newTilesAdded": 3, "nextExpansionCost": 100 }

Expansion Cost Formula:

// From n×n to (n+1)×(n+1) newTiles = (2 * currentSize) + 1 cost = newTiles * 10 * currentSize // Examples: // 1×1 → 2×2: 3 tiles * 10 * 1 = 30 water // 2×2 → 3×3: 5 tiles * 10 * 2 = 100 water // 3×3 → 4×4: 7 tiles * 10 * 3 = 210 water
GET /land/:playername

Purpose: View any player's farming land (public, no authentication required)

Examples:

GET /land/austin GET /land/farmergirl123

🎨 Visual Land Viewer:

GET /land/austin/view GET /land/farmergirl123/view

💡 The /view endpoint shows a beautiful visual color grid of the player's farm!

Response (land claimed):

{ "message": "austin's farming land", "playername": "austin", "landClaimed": true, "landTiles": 4, "gridSize": 2, "landData": [[0,0],[0,0]] }

Response (no land claimed):

{ "message": "austin has not claimed any land yet", "playername": "austin", "landClaimed": false, "landTiles": 0, "gridSize": 0, "landData": [] }
GET /land

Purpose: View your own farming land and what's on it

Headers:

Authorization: Bearer <your-access-token>

Response (land claimed):

{ "message": "Your farming land", "playername": "your-farmer-name", "landClaimed": true, "landTiles": 4, "gridSize": 2, "landData": [[0,0],[0,0]], "waterAvailable": 42, "nextExpansionCost": 100, "canExpand": false }

Response (no land):

{ "message": "No land claimed yet", "landClaimed": false, "claimCost": 5, "waterAvailable": 42, "canClaim": true }
GET /leaderboard

Purpose: View current farmer rankings (no authentication required)

Response:

{ "leaderboard": [ { "playername": "player1", "score": 100, "totalCalls": 102, "lastActivity": "2023-12-05T10:30:00.000Z", "land": { "claimed": true, "landTiles": 9, "gridSize": 3 } } ], "totalPlayers": 5 }
GET /crops

Purpose: Get comprehensive crop data with real-time market pricing (no authentication required)

🚨 NEW: Dynamic Market Pricing! This endpoint now provides live market prices that fluctuate ±15% every minute, plus market statistics and timing info for strategic farming decisions.

Response:

{ "message": "Available crops for planting (prices fluctuate every minute!)", "crops": [ { "type": "herb", "id": 2, "name": "Herb", "emoji": "🌿", "waterCost": 6, "growTimeHours": 0.11, "growTimeMinutes": 7, "creditsEarned": 0.5, "marketPrice": 0.5, "efficiency": 0.083, "description": "Quick growing herbs" }, // ... 18 more crops with current market prices ], "totalCrops": 19, "marketInfo": { "pricesLastUpdated": "2023-12-05T10:30:00.000Z", "nextPriceUpdate": "2023-12-05T10:31:00.000Z", "averagePrice": 10.15, "highestPrice": 29.0, "bestEfficiency": 0.396, "note": "Crop prices fluctuate ±15% every minute based on market dynamics!" }, "categories": { "starter": [/* crops ≤18 water */], "balanced": [/* crops 19-36 water */], "advanced": [/* crops 37-60 water */], "bulk": [/* crops >60 water */], "specialty": [/* unique strategy crops */] }, "maxWaterCost": 90, "maxCredits": 29.0, "bestEfficiency": 0.396, "timestamp": "2023-12-05T10:30:00.000Z" }

🚀 Script Usage Example:

// Monitor market for best deals const response = await fetch('/crops'); const data = await response.json(); // Find crops with above-average prices const avgPrice = data.marketInfo.averagePrice; const goodDeals = data.crops.filter(c => c.marketPrice > avgPrice); // Plant the best affordable high-priced crop const affordable = goodDeals.filter(c => c.waterCost <= myWater); const best = affordable.sort((a,b) => b.efficiency - a.efficiency)[0]; if (best) { await fetch('/plant', { method: 'POST', body: JSON.stringify({ cropType: best.type, row: 0, col: 0 }) }); }

💡 Key Fields for Market Trading:

marketPrice: Current fluctuating price (changes every minute) • efficiency: Current credits per water (recalculated with live prices) • marketInfo.averagePrice: Use to identify above/below average deals • marketInfo.nextPriceUpdate: When prices will change next • marketInfo.bestEfficiency: Current market leader efficiency
GET /activity

Purpose: View recent farm activities across all players (no authentication required)

Response:

{ "message": "Recent farm activities", "activities": [ { "timestamp": 1699188000000, "playername": "farmer123", "action": "harvested", "details": "Tomato", "result": "earned 6.2 credits", "emoji": "🍅", "timeAgo": "2m ago" }, { "timestamp": 1699187940000, "playername": "farmergirl", "action": "planted", "details": "Corn", "result": "invested 36 water", "emoji": "🌽", "timeAgo": "3m ago" } // ... up to 15 recent activities ], "totalActivities": 50, "timestamp": "2023-12-05T10:30:00.000Z" }

💡 Use Case: Perfect for monitoring farm activity, seeing what other players are doing, and getting inspiration for your own farming strategy. Activities include water collection milestones, land claims/expansions, crop planting, and harvesting.

GET /hello

Purpose: Test endpoint for JWT authentication (protected)

Headers:

Authorization: Bearer <your-access-token>

Response:

{ "message": "Hello, authenticated world!", "client_id": "your-client-id", "playername": "your-farmer-name", "timestamp": "2023-12-05T10:30:00.000Z" }

💡 Use Case: Useful for testing your JWT authentication flow and verifying that your tokens are working correctly before making more complex API calls.

GET /health

Purpose: Server health check (no authentication required)

Response:

{ "status": "OK", "timestamp": "2023-12-05T10:30:00.000Z" }

💡 Use Case: Perfect for monitoring scripts to check if the API server is running and responsive before attempting to make authenticated requests.

💡 Strategy Tips

🎯 Perfect Timing

The key to success is timing your /collect calls exactly 30 seconds apart. Too frequent = penalty, too slow = missed opportunities.

⚠️ Token Management

JWT tokens expire every 5 minutes. Make sure to refresh your token before it expires, or your increment calls will fail with a 401 error.

🔄 Robust Error Handling

Implement proper error handling for network issues, token expiration, and rate limiting. The most reliable scripts handle edge cases gracefully.

🏞️ Land Investment Strategy

Land claiming costs 5 water, but expansions get expensive quickly: 1×1→2×2 costs 30 water, 2×2→3×3 costs 100 water, etc. Plan your land investments carefully - balance water collection with land expansion!

🌾 Crop Farming Strategy

Once you have land, you can plant crops for credits! Each crop now has tripled water costs but grows 3x faster - creating a high-intensity farming environment. Water efficiency is more critical than ever! 🚨 NEW: Dynamic Pricing! Crop prices now fluctuate ±15% every minute, adding market timing to your strategy. Check out our comprehensive Crop Guide for detailed information, updated efficiency comparisons, and new market timing strategy tips for this dynamic farming environment!

💻 Your Challenge

🧠 Time to Code!

Now that you understand the API and rules, it's time to build your own script or application! Use any programming language or tool you're comfortable with to create a client that:

  • Registers your player to get unique credentials
  • Manages JWT token authentication and renewal every 5 minutes
  • Calls the increment endpoint with perfect timing (once every 30 seconds)
  • Handles errors, token expiration, and rate limiting gracefully
  • Runs continuously to maximize your score over time

Hint: The API documentation above shows you exactly what each endpoint expects. Think about timing, error handling, and state management. Good luck climbing the leaderboard! 🚀

⚡ Pro Tips

• Test your timing carefully - use precise intervals (not just sleep/setTimeout)
• Handle network failures and retry logic
• Monitor token expiration and refresh proactively
• Log your activity to debug issues
• Start simple, then optimize for reliability

🚀 Ready to Play?

🏁 Getting Started

Now that you understand the rules and API, build your script and deploy it! Watch the leaderboard to see your progress and compete with other players.

Pro tip: Start simple and add features like better error handling, logging, and monitoring as you go. The most reliable scripts win!