--- title: "DevPlace Admin API" description: "Administrator endpoints for users, roles, media, audit log, analytics and statistics, AI quota rules and resets, news curation, settings, bot fleet inspection, Devii tasks, backups and schedules, and Code Farm era control." language: null framework: null category: api_design tags: - devplace - api - http-api - admin - rest - audit-log - analytics - quotas - backups - user-management - operations keywords: - devplace admin users role toggle endpoint - devplace admin audit log api - devplace admin gateway quota rules endpoints - devplace admin backups run download schedule api - devplace admin statistics ai-usage data json last_updated: 2026-08-12 difficulty: advanced version: "DevPlace (devplace.net), documented 2026-08" related: - background_services_api.md - conventions_and_errors.md - authentication.md - README.md search_priority: normal status: published --- # DevPlace Admin API Site administration endpoints for users, news curation, and settings. Every call requires an **admin** account. Background service management lives on the [Background Services](background_services_api.md) page. Every endpoint follows the shared [Conventions & Errors](conventions_and_errors.md) (auth, content negotiation, pagination, status codes); see [Authentication](authentication.md) for the four ways to sign requests. ## `GET /admin/users` - List users Paginated user management page. Returns HTML. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `page` | query | int | no | Page number. | **Sample response** ```json { "users": [ { "uid": "UID", "username": "username", "avatar_seed": "string", "bio": "text", "location": "string", "git_link": "string", "website": "string", "level": 0, "xp": 0, "xp_progress_pct": 0, "xp_next_level": 0, "stars": 0, "created_at": "2026-01-01T00:00:00+00:00", "last_seen": "string", "role": "string", "email": "user@example.com", "is_active": false, "posts_count": 0 } ], "pagination": null, "admin_section": "string" } ``` ## `GET /admin/media` - Media trash Moderation view of deleted media. When a member or admin deletes an attachment it is soft-deleted: hidden from the gallery and from its parent object, but the row and file are kept and the relation to the parent is preserved. This page lists every soft-deleted attachment, newest first, with its uploader, so an admin can restore or permanently purge it. Returns HTML. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `page` | query | int | no | Page number. | ## `POST /media/{uid}/restore` - Restore media Restore a soft-deleted attachment. Because the parent relation is never cleared, it reappears in the owner's Media tab and on its original post, project, or gist immediately. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Soft-deleted attachment uid. | **Sample response** ```json { "ok": true, "redirect": "/admin/media" } ``` ## `POST /admin/awards/{uid}/revoke` - Revoke award Soft-delete a published award and its linked attachments, then recompute receiver stats. Restorable from admin trash. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Award uid to revoke. | **Sample response** ```json { "ok": true, "redirect": "/profile/receiver?tab=awards" } ``` ## `POST /admin/media/{uid}/purge` - Purge media Permanently delete a soft-deleted attachment: removes the database row and deletes the file from disk. This cannot be undone and is the only way media is hard-deleted from the UI. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Attachment uid to purge. | **Sample response** ```json { "ok": true, "redirect": "/admin/media" } ``` ## `GET /admin/audit-log` - Audit log Paginated, filterable audit event list (newest first, 25 per page). Negotiates HTML or JSON. Every state-changing action on the platform is recorded here with actor, origin, target, change, and result. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `page` | query | int | no | Page number. | | `event_key` | query | string | no | Filter by exact event key. | | `category` | query | string | no | Filter by category (auth, content, admin, container, ...). | | `actor_role` | query | string | no | Filter by actor role at action time. | | `actor_uid` | query | string | no | Filter by acting user uid. | | `origin` | query | string | no | Filter by origin (web, api, devii, cli, service, scheduler). | | `result` | query | string | no | Filter by result (success, failure, denied). | | `q` | query | string | no | Free-text search over summary, event key, and target. | | `date_from` | query | string | no | ISO date lower bound (inclusive). | | `date_to` | query | string | no | ISO date upper bound (inclusive). | **Sample response** ```json { "entries": [ { "uid": "AUDIT_UID", "created_at": "2026-06-11T20:00:00+00:00", "event_key": "admin.setting.update", "category": "admin", "actor_username": "ADMIN", "actor_role": "admin", "origin": "web", "via_agent": 0, "target_type": "setting", "old_value": "0", "new_value": "1", "result": "success" } ], "pagination": { "page": 1, "total": 1, "total_pages": 1 }, "filters": {}, "options": { "category": [ "admin", "auth", "content" ] } } ``` ## `GET /admin/audit-log/{uid}` - Audit event A single audit event with its full row and every related-object link. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Audit event uid. | **Sample response** ```json { "event": { "uid": "AUDIT_UID", "event_key": "container.instance.start", "result": "success" }, "links": [ { "relation": "actor", "object_type": "user", "object_uid": "USER_UID" }, { "relation": "instance", "object_type": "instance", "object_uid": "INSTANCE_UID" } ] } ``` ## `GET /admin/analytics` - Site analytics One-call aggregate analytics, returned as JSON: total members, active users in the last 24h/7d/30d, signed_in_now, new signups (24h/7d/30d), content totals (posts, comments, gists, projects, news), and top authors. Use this instead of paging the user list to count or measure activity. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `top_n` | query | int | no | How many top authors to include (1-50). | > `signed_in_now` counts members holding an unexpired session (logged in within the session lifetime, default 7-30 days), not a real-time online/presence count; the response carries a `signed_in_definition` explaining this. `active_*` means created content in the window (`active_definition`). > This is the endpoint the Devii assistant calls as `site_analytics`; see [Devii internals](https://devplace.net/docs/#doc-devii-internals). ## `GET /admin/statistics/data` - Platform statistics Tabbed platform statistics with KPI cards, period-over-period deltas, time-series data for charts, and breakdown tables. Covers visitors, members, content, engagement, social, AI, Devii, services, containers, game, awards, moderation, tools, and storage. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `tab` | query | string | no | Tab key (overview, visitors, members, content, ...). | | `hours` | query | int | no | Lookback window in hours (24, 168, 720, 2160, or 0 for all time). | | `compare` | query | int | no | Include previous-period comparison (1 or 0). | | `top_n` | query | int | no | Rows in breakdown tables (1-50). | > The HTML dashboard lives at `/admin/statistics`. Visitor metrics require the statistics tracking middleware (hourly aggregation, 90-day retention). ## `GET /admin/statistics` - Statistics dashboard Admin HTML dashboard for platform statistics with charts and tabs. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `tab` | query | string | no | Initial tab to render. | | `hours` | query | int | no | Initial time window in hours. | ## `GET /admin/ai-usage/data` - AI gateway usage analytics One-call AI gateway metrics, returned as JSON for a bounded time window: request volume and throughput, token usage with averages and percentiles (p50/p90/p95/p99), latency (upstream, gateway overhead, queue wait, connection establishment), error rates by category, cost in USD (per model, per caller, input vs output, projected monthly burn, caching savings), caller behavior, and an hourly breakdown. Cost is taken from the upstream native cost when present (OpenRouter) and computed from the configured per-million pricing otherwise (DeepSeek). *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `hours` | query | int | no | Lookback window in hours (1-168). | | `top_n` | query | int | no | How many rows in each top-N breakdown. | > TTFT and inter-token latency are not reported: the gateway forwards non-streaming to the upstream. ## `GET /admin/users/{uid}/ai-usage` - Per-user AI usage One user's AI gateway usage over the last 24 hours, returned as JSON: request volume, success and error rates, token totals, cost (window, per hour, per request, and a 30-day projection from the full 24h spend), average latency and throughput, a per-model breakdown, and an hourly cost series. Because Devii operates a signed-in user's account with that user's own API key, this is the user's complete gateway spend, whether driven through Devii or direct API calls. Shown admin-only on the user's profile page. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Target user UID. | | `hours` | query | int | no | Lookback window in hours (1-168). | **Sample response** ```json { "owner_id": "USER_UID", "window_hours": 24, "requests": 42, "success": 41, "failed": 1, "success_pct": 97.6, "error_pct": 2.4, "tokens": { "prompt": 120000, "completion": 38000, "total": 158000 }, "cost": { "window_usd": 0.214, "per_hour_usd": 0.0089, "per_request_usd": 0.0051, "projected_30d_usd": 6.42 }, "latency": { "avg_ms": 1830.0, "avg_tps": 41.2 }, "by_model": [ { "key": "molodetz", "requests": 42, "total_tokens": 158000, "cost_usd": 0.214 } ], "hourly": [ { "hour": "2026-06-08T16", "requests": 6, "cost_usd": 0.031, "total_tokens": 22000 } ] } ``` ## `POST /admin/users/{uid}/role` - Set a user role Promote or demote a user. You cannot change your own role. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Target user UID. | | `role` | form | enum | yes | New role. Allowed: member, admin. | **Sample response** ```json { "ok": true, "redirect": "/admin/users", "data": null } ``` ## `POST /admin/users/{uid}/password` - Reset a user password Set a new password for a user. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Target user UID. | | `password` | form | string | yes | New password, 6+ characters. | **Sample response** ```json { "ok": true, "redirect": "/admin/users", "data": null } ``` ## `POST /admin/users/{uid}/toggle` - Enable or disable a user Toggle a user's active state. You cannot disable yourself. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Target user UID. | **Sample response** ```json { "ok": true, "redirect": "/admin/users", "data": null } ``` ## `GET /admin/news` - List news articles Paginated news management page. Returns HTML. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `page` | query | int | no | Page number. | **Sample response** ```json { "articles": [ { "article": { "uid": "UID", "slug": "slug", "title": "Title", "description": "text", "content": "text", "url": "/path", "source_name": "string", "author": "string", "grade": 0, "ai_grade": 0, "status": "published", "image_url": "/path", "featured": 0, "has_unique_image": 0, "article_published": "string", "created_at": "2026-01-01T00:00:00+00:00", "synced_at": "2026-01-01T00:00:00+00:00" }, "time_ago": "2 hours ago", "synced_at": "2026-01-01T00:00:00+00:00", "grade": 0, "has_image": false } ], "pagination": null, "admin_section": "string" } ``` ## `POST /admin/news/{uid}/toggle` - Toggle featured Toggle an article's featured flag and lock it from the news service's auto-rotation. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Article UID. | **Sample response** ```json { "ok": true, "redirect": "/admin/news", "data": null } ``` ## `POST /admin/news/{uid}/publish` - Toggle published Switch an article between draft and published. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Article UID. | **Sample response** ```json { "ok": true, "redirect": "/admin/news", "data": null } ``` ## `POST /admin/news/{uid}/landing` - Toggle landing Toggle whether an article shows on the landing page and lock it from the news service's auto-rotation. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Article UID. | **Sample response** ```json { "ok": true, "redirect": "/admin/news", "data": null } ``` ## `POST /admin/news/{uid}/delete` - Delete a news article Delete an article and its images. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Article UID. | **Sample response** ```json { "ok": true, "redirect": "/admin/news", "data": null } ``` ## `GET /admin/settings` - Read site settings Return the current site and operational settings. Negotiates HTML or JSON. *Minimal role:* Admin **Sample response** ```json { "settings": {}, "admin_section": "string" } ``` ## `POST /admin/settings` - Save site settings Update operational and site settings. Empty fields are skipped. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `site_name` | form | string | no | Site name. | | `rate_limit_per_minute` | form | string | no | Requests per window. | | `registration_open` | form | enum | no | Allow signups. Allowed: 1, 0. | | `maintenance_mode` | form | enum | no | Maintenance gate. Allowed: 1, 0. | > Accepts every field on the admin settings form; only non-empty values are written. **Sample response** ```json { "ok": true, "redirect": "/admin/settings", "data": null } ``` ## `POST /admin/notifications` - Set a notification default Set the platform-wide default for one notification type on one channel. Applies to users who have not customized that notification; explicit user choices are unaffected. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `notification_type` | form | string | yes | One of: comment, reply, mention, vote, follow, message, badge, level, issue, reminder, harvest_stolen. | | `channel` | form | string | yes | One of in_app, push or telegram (telegram is off by default and requires a paired Telegram account). | | `value` | form | boolean | no | 1 to enable this notification by default, 0 to disable. | **Sample response** ```json { "ok": true, "redirect": "/admin/notifications", "data": { "notification_type": "vote", "channel": "push", "value": false } } ``` ## `POST /admin/users/{uid}/reset-ai-quota` - Reset user AI quota Delete a specific user's AI gateway ledger rows, resetting their quota. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Target user UID. | ## `POST /admin/ai-quota/reset-guests` - Reset guest AI quotas Reset AI quota for all anonymous guest users. *Minimal role:* Admin ## `POST /admin/ai-quota/reset-all` - Reset all AI quotas Reset AI quota for every user (members and guests). *Minimal role:* Admin ## `GET /admin/gateway/quota-rules` - List AI gateway quota rules List every rolling-24h USD quota rule on /openai/v1/*, each scoped by any combination of role, specific user uid, and app_reference label, plus the global per-role default caps that apply when no rule matches. *Minimal role:* Admin ## `POST /admin/gateway/quota-rules` - Create or update an AI gateway quota rule Caps rolling-24h USD spend on /openai/v1/*. At least one of owner_kind, owner_id, app_reference must be set; leaving a dimension blank makes it a wildcard, and the most specific active match wins over other rules and over the global default. Pass uid to update an existing rule. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | json | string | no | Existing rule uid to update; omit to create a new rule. | | `owner_kind` | json | string | no | internal, key, user, admin, or anonymous. Blank = any role. | | `owner_id` | json | string | no | Specific user uid. Blank = any caller of the matched role. | | `app_reference` | json | string | no | App label (the X-App-Reference header). Blank = any app. | | `limit_usd` | json | number | yes | Rolling 24h USD cap. 0 = unlimited. | | `is_active` | json | boolean | no | Whether the rule is enforced. | | `label` | json | string | no | Optional admin-facing note. | ## `POST /admin/gateway/quota-resets` - Reset the AI gateway 24h spend Clear the counted rolling-24h spend for a scope so a capped caller can call again, without deleting any usage history (the cost analytics stay intact). Scope it exactly like a quota rule; leaving all three dimensions blank resets every caller. Only spend recorded before the reset is cleared - new calls count again immediately against the same limit. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `owner_kind` | json | string | no | internal, key, user, admin, or anonymous. Blank = every role. | | `owner_id` | json | string | no | Specific user uid. Blank = every caller. | | `app_reference` | json | string | no | App label (the X-App-Reference header). Blank = every app. | ## `DELETE /admin/gateway/quota-rules/{uid}` - Delete an AI gateway quota rule Delete a quota rule; callers it covered fall back to the next most specific rule or the global default. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Quota rule uid. | ## `GET /admin/bots` - Bot monitor page Live low-quality screenshot grid of every running bot persona, one frame per bot. *Minimal role:* Admin **Sample response** ```json { "frames": [ { "slot": 0, "username": "username", "persona": "string", "action": "string", "status": "published", "url": "/path", "label": "string", "captured_at": 0, "age_seconds": 0, "has_image": false, "active": false, "frame_url": "/path" } ], "enabled": false, "service_status": "published", "admin_section": "string", "user": null } ``` ## `GET /admin/bots/data` - Bot monitor data JSON of every running bot slot with its label, persona, current action/status, and latest frame URL for polling. *Minimal role:* Admin **Sample response** ```json { "enabled": true, "service_status": "running", "frames": [ { "slot": 0, "username": "bytewren", "persona": "grumpy_senior", "action": "POST: rant [3]", "status": "page load", "url": "https://example.com/feed", "label": "bytewren", "captured_at": 1718366400, "age_seconds": 2, "has_image": true, "active": true, "frame_url": "/admin/bots/0/frame.jpg?t=1718366400" } ] } ``` ## `GET /admin/bots/{slot}/frame.jpg` - Bot frame image The latest low-quality JPEG screenshot for one bot slot (no-store). *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `slot` | path | integer | yes | Bot fleet slot index. | ## `GET /admin/devii-tasks` - Scheduled Devii tasks Every scheduled Devii task across all owners with its schedule, run count, expiry, failure streak, and whether its owner may still schedule, plus the configured automation bounds. Returns HTML (or JSON with Accept: application/json). *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `state` | query | string | no | One of active, inactive, all. | ## `POST /admin/devii-tasks/{uid}/disable` - Disable a scheduled task Stop one scheduled task. The row is kept and stays auditable. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Uid of the task. | ## `POST /admin/devii-tasks/{uid}/delete` - Delete a scheduled task Soft-delete one scheduled task; it moves to the admin trash. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Uid of the task. | ## `GET /admin/backups` - Backups dashboard Storage usage, every backup archive, and every backup schedule. Returns HTML (or JSON with Accept: application/json). *Minimal role:* Admin ## `GET /admin/backups/data` - Backups data JSON dashboard payload: per-path storage usage, total data and backup size, disk usage, the backup list, and the schedule list. *Minimal role:* Admin ## `POST /admin/backups/run` - Create backup Enqueue an async backup job for a target (database, uploads, keys, full). Returns the job uid and a status_url. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `target` | form | string | yes | One of database, uploads, keys, full. | **Sample response** ```json { "ok": true, "uid": "JOB_UID", "backup_uid": "BACKUP_UID", "status_url": "/admin/backups/jobs/JOB_UID" } ``` ## `GET /admin/backups/jobs/{uid}` - Backup job status Status of one backup job (pending, running, done, failed) with archive stats. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Backup job uid. | **Sample response** ```json { "uid": "JOB_UID", "kind": "backup", "status": "done", "target": "full", "backup_uid": "BACKUP_UID", "download_url": "/admin/backups/BACKUP_UID/download", "bytes_out": 10485760, "file_count": 1240, "sha256": "\u2026" } ``` ## `GET /admin/backups/{uid}/download` - Download backup Stream a completed backup archive as a tar.gz file. Restricted to the primary administrator (the first user created with the Admin role); every other administrator receives 403 Forbidden. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Backup uid. | ## `POST /admin/backups/{uid}/delete` - Delete backup Permanently delete a backup archive and reclaim its disk space. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Backup uid. | **Sample response** ```json { "ok": true, "redirect": "/admin/backups" } ``` ## `POST /admin/backups/schedules/create` - Create backup schedule Create a recurring backup. kind=interval uses every_seconds; kind=cron uses a 5-field cron expression. keep_last rotates older backups of the schedule. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `name` | form | string | yes | Schedule name. | | `target` | form | string | yes | Backup target. | | `kind` | form | string | yes | interval or cron. | | `every_seconds` | form | int | no | Seconds between runs (kind=interval). | | `cron` | form | string | no | Cron expression (kind=cron). | | `keep_last` | form | int | no | Keep only the newest N (0 = all). | **Sample response** ```json { "ok": true, "redirect": "/admin/backups" } ``` ## `POST /admin/backups/schedules/{uid}/edit` - Edit backup schedule Update a backup schedule's target, trigger, and retention. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Schedule uid. | | `name` | form | string | yes | Schedule name. | | `target` | form | string | yes | Backup target. | | `kind` | form | string | yes | interval or cron. | | `every_seconds` | form | int | no | Seconds between runs (kind=interval). | | `cron` | form | string | no | Cron expression (kind=cron). | | `keep_last` | form | int | no | Keep only the newest N (0 = all). | **Sample response** ```json { "ok": true, "redirect": "/admin/backups" } ``` ## `POST /admin/backups/schedules/{uid}/toggle` - Toggle backup schedule Enable or disable a backup schedule. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Schedule uid. | **Sample response** ```json { "ok": true, "redirect": "/admin/backups" } ``` ## `POST /admin/backups/schedules/{uid}/run` - Run backup schedule now Immediately enqueue a backup for a schedule without waiting for its next run. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Schedule uid. | **Sample response** ```json { "ok": true, "redirect": "/admin/backups" } ``` ## `POST /admin/backups/schedules/{uid}/delete` - Delete backup schedule Delete a backup schedule. Existing archives are kept. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `uid` | path | string | yes | Schedule uid. | **Sample response** ```json { "ok": true, "redirect": "/admin/backups" } ``` ## `GET /admin/game` - Code Farm Era management View the current Code Farm Era status. *Minimal role:* Admin **Sample response** ```json { "era_active": false, "era_name": "" } ``` ## `POST /admin/game/era/start` - Start an Era Start a new Code Farm Era: resets every farm's visible Era coins/harvests counters to zero. Real coins, prestige, stars, Legacy, and Mastery are never touched. *Minimal role:* Admin **Parameters** | Name | In | Type | Required | Description | |------|----|------|----------|-------------| | `name` | form | string | yes | Era name. | | `duration_days` | form | int | no | Planned Era length in days. | **Sample response** ```json { "ok": true, "redirect": "/admin/game" } ``` ## `POST /admin/game/era/end` - End the running Era End the current Era: ranks every participating farm by Era score, awards Stars to the top 10 (and an Era-exclusive cosmetic when available), and permanently records the results. *Minimal role:* Admin **Sample response** ```json { "ok": true, "redirect": "/admin/game" } ```