platforms/devplace/admin_api.md

DevPlace Admin API

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.

Site administration endpoints for users, news curation, and settings. Every call requires an admin account. Background service management lives on the Background Services page.

Every endpoint follows the shared Conventions & Errors (auth, content negotiation, pagination, status codes); see Authentication for the four ways to sign requests.

GET /admin/users - List users

Paginated user management page. Returns HTML.

Minimal role: Admin

Parameters

NameInTypeRequiredDescription
pagequeryintnoPage number.

Sample response

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

NameInTypeRequiredDescription
pagequeryintnoPage 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

NameInTypeRequiredDescription
uidpathstringyesSoft-deleted attachment uid.

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesAward uid to revoke.

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesAttachment uid to purge.

Sample response

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

NameInTypeRequiredDescription
pagequeryintnoPage number.
event_keyquerystringnoFilter by exact event key.
categoryquerystringnoFilter by category (auth, content, admin, container, ...).
actor_rolequerystringnoFilter by actor role at action time.
actor_uidquerystringnoFilter by acting user uid.
originquerystringnoFilter by origin (web, api, devii, cli, service, scheduler).
resultquerystringnoFilter by result (success, failure, denied).
qquerystringnoFree-text search over summary, event key, and target.
date_fromquerystringnoISO date lower bound (inclusive).
date_toquerystringnoISO date upper bound (inclusive).

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesAudit event uid.

Sample response

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

NameInTypeRequiredDescription
top_nqueryintnoHow many top authors to include (1-50).

signedinnow 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 signedindefinition explaining this. active* means created content in the window (activedefinition).

This is the endpoint the Devii assistant calls as site_analytics; see 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

NameInTypeRequiredDescription
tabquerystringnoTab key (overview, visitors, members, content, ...).
hoursqueryintnoLookback window in hours (24, 168, 720, 2160, or 0 for all time).
comparequeryintnoInclude previous-period comparison (1 or 0).
top_nqueryintnoRows 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

NameInTypeRequiredDescription
tabquerystringnoInitial tab to render.
hoursqueryintnoInitial 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

NameInTypeRequiredDescription
hoursqueryintnoLookback window in hours (1-168).
top_nqueryintnoHow 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

NameInTypeRequiredDescription
uidpathstringyesTarget user UID.
hoursqueryintnoLookback window in hours (1-168).

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesTarget user UID.
roleformenumyesNew role. Allowed: member, admin.

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesTarget user UID.
passwordformstringyesNew password, 6+ characters.

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesTarget user UID.

Sample response

{
  "ok": true,
  "redirect": "/admin/users",
  "data": null
}

GET /admin/news - List news articles

Paginated news management page. Returns HTML.

Minimal role: Admin

Parameters

NameInTypeRequiredDescription
pagequeryintnoPage number.

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesArticle UID.

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesArticle UID.

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesArticle UID.

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesArticle UID.

Sample response

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

{
  "settings": {},
  "admin_section": "string"
}

POST /admin/settings - Save site settings

Update operational and site settings. Empty fields are skipped.

Minimal role: Admin

Parameters

NameInTypeRequiredDescription
site_nameformstringnoSite name.
ratelimitper_minuteformstringnoRequests per window.
registration_openformenumnoAllow signups. Allowed: 1, 0.
maintenance_modeformenumnoMaintenance gate. Allowed: 1, 0.

Accepts every field on the admin settings form; only non-empty values are written.

Sample response

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

NameInTypeRequiredDescription
notification_typeformstringyesOne of: comment, reply, mention, vote, follow, message, badge, level, issue, reminder, harvest_stolen.
channelformstringyesOne of in_app, push or telegram (telegram is off by default and requires a paired Telegram account).
valueformbooleanno1 to enable this notification by default, 0 to disable.

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesTarget 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 ownerkind, ownerid, 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

NameInTypeRequiredDescription
uidjsonstringnoExisting rule uid to update; omit to create a new rule.
owner_kindjsonstringnointernal, key, user, admin, or anonymous. Blank = any role.
owner_idjsonstringnoSpecific user uid. Blank = any caller of the matched role.
app_referencejsonstringnoApp label (the X-App-Reference header). Blank = any app.
limit_usdjsonnumberyesRolling 24h USD cap. 0 = unlimited.
is_activejsonbooleannoWhether the rule is enforced.
labeljsonstringnoOptional 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

NameInTypeRequiredDescription
owner_kindjsonstringnointernal, key, user, admin, or anonymous. Blank = every role.
owner_idjsonstringnoSpecific user uid. Blank = every caller.
app_referencejsonstringnoApp 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

NameInTypeRequiredDescription
uidpathstringyesQuota 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

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

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

NameInTypeRequiredDescription
slotpathintegeryesBot 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

NameInTypeRequiredDescription
statequerystringnoOne 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

NameInTypeRequiredDescription
uidpathstringyesUid 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

NameInTypeRequiredDescription
uidpathstringyesUid 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

NameInTypeRequiredDescription
targetformstringyesOne of database, uploads, keys, full.

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesBackup job uid.

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesBackup uid.

POST /admin/backups/{uid}/delete - Delete backup

Permanently delete a backup archive and reclaim its disk space.

Minimal role: Admin

Parameters

NameInTypeRequiredDescription
uidpathstringyesBackup uid.

Sample response

{
  "ok": true,
  "redirect": "/admin/backups"
}

POST /admin/backups/schedules/create - Create backup schedule

Create a recurring backup. kind=interval uses everyseconds; kind=cron uses a 5-field cron expression. keeplast rotates older backups of the schedule.

Minimal role: Admin

Parameters

NameInTypeRequiredDescription
nameformstringyesSchedule name.
targetformstringyesBackup target.
kindformstringyesinterval or cron.
every_secondsformintnoSeconds between runs (kind=interval).
cronformstringnoCron expression (kind=cron).
keep_lastformintnoKeep only the newest N (0 = all).

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesSchedule uid.
nameformstringyesSchedule name.
targetformstringyesBackup target.
kindformstringyesinterval or cron.
every_secondsformintnoSeconds between runs (kind=interval).
cronformstringnoCron expression (kind=cron).
keep_lastformintnoKeep only the newest N (0 = all).

Sample response

{
  "ok": true,
  "redirect": "/admin/backups"
}

POST /admin/backups/schedules/{uid}/toggle - Toggle backup schedule

Enable or disable a backup schedule.

Minimal role: Admin

Parameters

NameInTypeRequiredDescription
uidpathstringyesSchedule uid.

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesSchedule uid.

Sample response

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

NameInTypeRequiredDescription
uidpathstringyesSchedule uid.

Sample response

{
  "ok": true,
  "redirect": "/admin/backups"
}

GET /admin/game - Code Farm Era management

View the current Code Farm Era status.

Minimal role: Admin

Sample response

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

NameInTypeRequiredDescription
nameformstringyesEra name.
duration_daysformintnoPlanned Era length in days.

Sample response

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

{
  "ok": true,
  "redirect": "/admin/game"
}