Steam Integration API
Track gaming achievements, social tasks, and daily activities through the Steam integration system.
Base URL
https://app.farfish.xyz/api/steam
Platform Note: All gaming features (Steam integration, fishing, tasks) are available across all FarFISH apps - Web App, Base App, Farcaster Mini App, and Android App.
GET /api/steam/task-status
Get all Steam-related task completion status for a wallet.
Request
Endpoint: GET /api/steam/task-status?wallet={address}
Query Parameters:
wallet(required) - Ethereum wallet address
Example:
GET /api/steam/task-status?wallet=0x742d35cc6634c0532925a3b844bc9e7595f0beb9
Response
Success (200):
{
"wallet": "0x742d35cc6634c0532925a3b844bc9e7595f0beb9",
"tasks": {
"daily_checkin": false,
"add_miniapp": true,
"fc_follow": true,
"fc_like_recast": false,
"fc_comment": false,
"referral": true,
"referral_milestone_5": true,
"referral_milestone_10": false,
"referral_milestone_30": false,
"referral_milestone_50": false,
"nft_mint": true
},
"fishingCooldown": 43200,
"timestamp": "2025-01-12T10:30:00.000Z"
}
Response Schema:
{
wallet: string; // Queried wallet address
tasks: {
daily_checkin: boolean; // true = on cooldown, false = available
add_miniapp: boolean; // Added mini app to Farcaster
fc_follow: boolean; // Followed on Farcaster
fc_like_recast: boolean; // Liked/recasted post
fc_comment: boolean; // Commented on post
referral: boolean; // Made at least 1 referral
referral_milestone_5: boolean; // 5+ referrals
referral_milestone_10: boolean; // 10+ referrals
referral_milestone_30: boolean; // 30+ referrals
referral_milestone_50: boolean; // 50+ referrals
nft_mint: boolean; // Owns FarFISH NFT
};
fishingCooldown: number; // Seconds until daily checkin available (0 = ready)
timestamp: string; // ISO timestamp of response
}
Daily Checkin (Fishing) Cooldown
Cooldown Duration: 24 hours (86,400 seconds)
Availability Logic:
const lastFishing = user.steam.fishing.last; // Unix timestamp
const now = Date.now() / 1000;
const elapsed = now - lastFishing;
if (elapsed >= 86400) {
// Available to claim
tasks.daily_checkin = false;
fishingCooldown = 0;
} else {
// On cooldown
tasks.daily_checkin = true;
fishingCooldown = 86400 - elapsed; // Seconds remaining
}
Task Completion Rewards
Completing Steam tasks contributes to overall progress and may unlock rewards like FRH bonuses or special NFTs.
cURL Example
curl "https://app.farfish.xyz/api/steam/task-status?wallet=0x742d35cc6634c0532925a3b844bc9e7595f0beb9"
JavaScript Example
async function getTaskStatus(wallet: string) {
const response = await fetch(
`https://app.farfish.xyz/api/steam/task-status?wallet=${wallet}`
);
const data = await response.json();
console.log('Fishing cooldown:', data.fishingCooldown, 'seconds');
console.log('Tasks completed:',
Object.entries(data.tasks)
.filter(([_, completed]) => completed)
.map(([task]) => task)
);
return data;
}
POST /api/steam/task/complete
Mark a Steam task as completed.
Request
Endpoint: POST /api/steam/task/complete
Headers:
Content-Type: application/json
Body Schema:
{
wallet: string; // Ethereum wallet address
taskId: string; // Task identifier
}
Valid Task IDs:
daily_checkin- Daily fishing taskadd_miniapp- Add mini app to Farcasterfc_follow- Follow on Farcasterfc_like_recast- Like/recast postfc_comment- Comment on post
Example Request:
{
"wallet": "0x742d35cc6634c0532925a3b844bc9e7595f0beb9",
"taskId": "daily_checkin"
}
Response
Success (200):
{
"success": true,
"taskId": "daily_checkin",
"timestamp": 1705056000
}
Error (400):
{
"error": "Task on cooldown",
"cooldownRemaining": 43200
}
Daily Checkin Special Behavior
The daily_checkin task has unique cooldown handling:
Data Updated: Task completion timestamp is recorded in the backend.
Cooldown Enforcement:
- Cannot complete if less than 24 hours since last completion
- Cooldown calculated server-side (untrusted client timestamps)
Other Tasks
Data Updated: Task completion is recorded with timestamp in the backend.
Idempotent: Completing already-completed task returns success.
cURL Example
curl -X POST https://app.farfish.xyz/api/steam/task/complete \
-H "Content-Type: application/json" \
-d '{
"wallet": "0x742d35cc6634c0532925a3b844bc9e7595f0beb9",
"taskId": "daily_checkin"
}'
JavaScript Example
async function completeTask(wallet: string, taskId: string) {
const response = await fetch('https://app.farfish.xyz/api/steam/task/complete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ wallet, taskId })
});
const data = await response.json();
if (data.success) {
console.log(`Task ${taskId} completed!`);
} else {
console.error('Error:', data.error);
}
}
POST /api/steam/verify
Verify on-chain task completion (NFT minting, staking).
Request
Endpoint: POST /api/steam/verify
Headers:
Content-Type: application/json
Body Schema:
{
wallet: string; // Ethereum wallet address
taskId: string; // Task to verify
}
Verifiable Tasks:
nft_mint- Verify NFT ownership or active stake
Example Request:
{
"wallet": "0x742d35cc6634c0532925a3b844bc9e7595f0beb9",
"taskId": "nft_mint"
}
Response
Success (200):
{
"success": true,
"taskId": "nft_mint",
"verified": true
}
Failure (200):
{
"success": false,
"taskId": "nft_mint",
"verified": false,
"reason": "No NFTs owned and no active stakes"
}
NFT Mint Verification Logic
Checks on-chain state via Base blockchain RPC:
-
Check NFT Balance:
typescriptconst balance = await nftContract.read.balanceOf([wallet]); if (balance > 0) return true; // Has NFT -
Check Active Stakes:
typescriptconst stakeIds = await stakingContract.read.getUserStakeIds([wallet]); if (stakeIds.length > 0) return true; // Has staked NFTs -
Result:
- If either check passes, task marked completed
- Data stored:
user:{wallet}.tasks.nft_mint = true
Verification Frequency
Verification can be called multiple times. Useful for:
- Checking if task auto-completed after minting
- Re-verifying after staking
- Updating UI state after on-chain transactions
cURL Example
curl -X POST https://app.farfish.xyz/api/steam/verify \
-H "Content-Type: application/json" \
-d '{
"wallet": "0x742d35cc6634c0532925a3b844bc9e7595f0beb9",
"taskId": "nft_mint"
}'
JavaScript Example
async function verifyTask(wallet: string, taskId: string) {
const response = await fetch('https://app.farfish.xyz/api/steam/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ wallet, taskId })
});
const data = await response.json();
if (data.verified) {
console.log(`Task ${taskId} verified!`);
} else {
console.log(`Task ${taskId} not yet completed:`, data.reason);
}
}
GET /api/steam/progress
Get user's overall Steam progress with auto-verification.
Request
Endpoint: GET /api/steam/progress?wallet={address}
Query Parameters:
wallet(required) - Ethereum wallet address
Example:
GET /api/steam/progress?wallet=0x742d35cc6634c0532925a3b844bc9e7595f0beb9
Response
Success (200):
{
"progress": {
"nft_mint": true,
"fc_follow": true,
"fc_like_recast": false,
"referral": true,
"referral_milestone_5": true
},
"referralCount": 7
}
Response Schema:
{
progress: Record<string, boolean>; // Task completion map
referralCount: number; // Total referrals made
}
Auto-Verification Behavior
On every request, this endpoint automatically:
- Calls
/api/steam/verifyfornft_minttask - Updates task completion status if verification passes
- Returns current progress including auto-verified tasks
Benefits:
- UI stays up-to-date with on-chain state
- No manual verification button needed
- Seamless task completion after minting/staking
cURL Example
curl "https://app.farfish.xyz/api/steam/progress?wallet=0x742d35cc6634c0532925a3b844bc9e7595f0beb9"
JavaScript Example
async function getSteamProgress(wallet: string) {
const response = await fetch(
`https://app.farfish.xyz/api/steam/progress?wallet=${wallet}`
);
const data = await response.json();
const completedTasks = Object.keys(data.progress).filter(
task => data.progress[task]
);
console.log('Completed tasks:', completedTasks);
console.log('Total referrals:', data.referralCount);
return data;
}
Backend Data Model
User Steam Data Structure
{
steam: {
fishing: {
last: number // Unix timestamp of last daily checkin
},
add_app: {
completed: boolean,
ts: number // Completion timestamp
},
follow: {
completed: boolean,
ts: number
},
like_recast: {
completed: boolean,
ts: number
},
comment: {
completed: boolean,
ts: number
}
},
tasks: {
nft_mint: boolean, // On-chain verified
referral: boolean,
referral_milestone_5: boolean,
referral_milestone_10: boolean,
referral_milestone_30: boolean,
referral_milestone_50: boolean
}
}
Referral Milestone Logic
Referral milestones auto-update based on refcount:{wallet}:
const referralCount = await backend.get(`refcount for wallet`);
tasks.referral = referralCount >= 1;
tasks.referral_milestone_5 = referralCount >= 5;
tasks.referral_milestone_10 = referralCount >= 10;
tasks.referral_milestone_30 = referralCount >= 30;
tasks.referral_milestone_50 = referralCount >= 50;
Integration Example
Complete Steam task tracking UI:
// Get wallet address from your Web3 connection library
const { address } = useWalletConnection();
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
function useSteamTasks() {
const { address } = useAccount();
const queryClient = useQueryClient();
// Fetch task status
const { data: status, isLoading } = useQuery({
queryKey: ['steam', 'status', address],
queryFn: async () => {
const res = await fetch(`/api/steam/task-status?wallet=${address}`);
return res.json();
},
enabled: !!address,
refetchInterval: 10_000, // Poll every 10 seconds
});
// Complete task mutation
const completeTask = useMutation({
mutationFn: async (taskId: string) => {
const res = await fetch('/api/steam/task/complete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ wallet: address, taskId })
});
return res.json();
},
onSuccess: () => {
// Refetch status after completion
queryClient.invalidateQueries({ queryKey: ['steam', 'status', address] });
},
});
return { status, isLoading, completeTask };
}
// Usage
function SteamDashboard() {
const { status, isLoading, completeTask } = useSteamTasks();
if (isLoading) return <div>Loading...</div>;
const dailyAvailable = status.fishingCooldown === 0;
return (
<div>
<h2>Daily Checkin</h2>
{dailyAvailable ? (
<button onClick={() => completeTask.mutate('daily_checkin')}>
Claim Daily Reward
</button>
) : (
<p>Next claim in: {Math.floor(status.fishingCooldown / 3600)} hours</p>
)}
<h2>Social Tasks</h2>
<ul>
<li>Follow: {status.tasks.fc_follow ? '✅' : '⬜'}</li>
<li>Like/Recast: {status.tasks.fc_like_recast ? '✅' : '⬜'}</li>
<li>Comment: {status.tasks.fc_comment ? '✅' : '⬜'}</li>
</ul>
<h2>Milestones</h2>
<ul>
<li>1 Referral: {status.tasks.referral ? '✅' : '⬜'}</li>
<li>5 Referrals: {status.tasks.referral_milestone_5 ? '✅' : '⬜'}</li>
<li>10 Referrals: {status.tasks.referral_milestone_10 ? '✅' : '⬜'}</li>
</ul>
</div>
);
}
Error Handling
| Error | HTTP Status | Meaning | Action |
|---|---|---|---|
Task on cooldown | 400 | Cannot complete yet | Display cooldown timer |
Invalid task ID | 400 | Unknown taskId | Check valid task list |
Verification failed | 200 | On-chain check failed | User hasn't completed requirement |
| Server error | 500 | Backend/RPC issue | Retry with exponential backoff |
Related Documentation
- User API - User profile & account linking
- Referral API - Referral milestone tracking