--- title: Admin API tags: [api, admin, reference] --- # Admin API > **Last updated:** 2026-05-29 — aligned with code (see [Doc vs Code Audit Report](../09%20-%20Audits/Doc%20vs%20Code%20Audit%20Report%20-%202026-05-29.md)) There is no single `/api/admin` namespace — admin-only endpoints are scattered across the service routers. This page catalogs them in one place. All require `Bearer JWT` with `req.user.role === 'admin'`. The two enforcement patterns are: - Middleware: `authorizeRoles('admin')` after `authenticateToken` (used by the dispute, data-cleanup, blog routers). - Inline check inside the handler: `if (req.user.role !== 'admin') return 403` (used by user, points, payment routes). ## User management See full descriptions in [[User API]]. | Endpoint | Action | | --- | --- | | `POST /api/user/admin/create` | Create user with role/status | | `DELETE /api/user/admin/:userId` | Soft delete user — sets `status='deleted'` (admins cannot delete each other) | | `PATCH /api/user/admin/:userId/status` | Activate / suspend | | `PATCH /api/user/admin/:userId/toggle-status` | Flip active flag | | `PATCH /api/user/admin/:userId/role` | Change role | | `GET /api/user/admin/list` | Paginated directory + stats | | `GET /api/user/admin/:userId/dependencies` | Pre-delete dependency check | | `GET /api/users/admin/stats` | Aggregate user analytics | | `GET /api/users/admin/:userId` | Full user detail (admin view) | | `PUT /api/users/admin/:userId` | Mass update user | | `PUT /api/users/admin/update/:email` | Mass update by email | | `PATCH /api/users/admin/:userId/password` | Force password reset (wipes refresh tokens) | | `POST /api/users/admin/:userId/resend-verification` | Resend verification email | **⚠️ KNOWN BUG — HTTP verb mismatch (status/role updates):** The frontend Redux actions for `updateUserStatus` and `updateUserRole` send `PUT` requests, but the backend registers these handlers under `PATCH`. These calls will receive `404 Method Not Found` responses until the frontend is corrected to use `PATCH`. **⚠️ KNOWN BUG — Status value mismatch:** The frontend sends `'inactive'` and `'pending'` as status values when updating user status. The backend only accepts `'active'`, `'suspended'`, or `'deleted'`. Sending `'inactive'` or `'pending'` will be rejected or silently ignored. **Hard vs. soft delete note:** The legacy route `DELETE /users/admin/:id` performs a **hard delete** (`findByIdAndDelete`). The current route `DELETE /api/user/admin/:userId` performs a **soft delete** (sets `status='deleted'`). Always use the current `/api/user/admin/:userId` route to preserve data integrity. ## Listing / marketplace moderation See [[Marketplace API]]. Admins can use most marketplace endpoints with elevated privileges (e.g. delete any purchase request, override offer status). Specific admin-only actions: | Endpoint | Action | | --- | --- | | `PUT /api/marketplace/offers/:id/status` | Direct status mutation including admin overrides | | `POST /api/marketplace/purchase-requests/:id/release-payment` | Force escrow release | | `PATCH /api/marketplace/purchase-requests/:id/status` (any → any) | Override request state machine | Template approval is implicit: admins use the same template CRUD endpoints with override privileges. ## Dispute mediation See [[Dispute API]]. | Endpoint | Action | | --- | --- | | `POST /api/disputes/:id/assign` | Assign moderator | | `PATCH /api/disputes/:id/status` | Update status | | `POST /api/disputes/:id/resolve` | Final decision (buyer / seller / split) | | `GET /api/disputes/statistics` | Admin dashboard data | ## Manual payment operations See [[Payment API]]. | Endpoint | Action | | --- | --- | | `POST /api/payment/payments/cleanup-pending` | Delete stale pending payments | | `POST /api/payment/payments/:id/fetch-tx` | Re-query chain for missing tx hash | | `POST /api/payment/payments/auto-fetch-missing` | Batch tx-hash backfill | | `POST /api/payment/:id/release` | Build escrow-release tx | | `POST /api/payment/:id/release/confirm` | Confirm release tx hash | | `POST /api/payment/:id/refund` | Build refund tx | | `POST /api/payment/:id/refund/confirm` | Confirm refund tx hash | | `POST /api/payment/shkeeper/payout` | Create payout task | | `GET /api/payment/shkeeper/webhook-stats` | Webhook telemetry | | `POST /api/payment/decentralized/admin-payout` | Direct admin-wallet payout | **⚠️ Path correction:** Release/refund routes do **not** include a `/shkeeper/` segment. The correct paths are `/api/payment/:id/release`, `/api/payment/:id/release/confirm`, etc. (Previously documented incorrectly as `/api/payment/shkeeper/:id/…`.) ## Points (admin) See [[Points API]]. | Endpoint | Action | | --- | --- | | `POST /api/points/admin/add` | Manually grant / deduct points for a user | ## Data cleanup Router: [`backend/src/services/admin/dataCleanupRoutes.ts`](../../backend/src/services/admin/dataCleanupRoutes.ts). Mounted under `/api/admin/cleanup/*`. The router applies `authenticateToken` + `authorizeRoles('admin')` to every endpoint. ### GET /api/admin/cleanup/stats **Description:** Per-collection document counts and sizes. **Response 200:** `{ success, data: { collections: [{ name, count, sizeBytes }] } }` ### GET /api/admin/cleanup/collections **Description:** List collections that can be cleaned and the supported flags. **Response 200:** `{ success, data: { collections, options } }` ### POST /api/admin/cleanup/clean **Description:** Bulk delete records. Defaults to `dryRun: true` and `keepAdmins: true`. **Request body:** ```ts { collections?: string[]; // default ["all"] dryRun?: boolean; // default true keepAdmins?: boolean; // default true olderThanDays?: number; // optional age filter confirm?: "DELETE_ALL_DATA"; // required for actual deletion } ``` **Response 200:** `{ success, data: { deletedCounts, dryRun } }` ### DELETE /api/admin/cleanup/user/:userId **Description:** Cascade-delete all data for a specific user (GDPR). Requires `?confirm=DELETE_USER_DATA` for real execution. **Query params:** `dryRun=true|false`, `confirm=DELETE_USER_DATA` ### POST /api/admin/cleanup/temp **Description:** Purge temporary data older than N hours (verification codes, file temp uploads). **Request body:** `{ olderThanHours?: number }` (default 24) ### POST /api/admin/cleanup/seed-templates **Description:** Re-runs the request templates seeder (production safe; idempotent). ### POST /api/admin/cleanup/seed-all **Description:** Seeds users, addresses, and templates in dependency order. Used to bootstrap a fresh staging environment. ## Scanner / monitoring ### GET /api/admin/scanner/status **Description:** Returns the current state of the blockchain scanner / wallet monitor. **⚠️ SECURITY BUG — NO AUTHENTICATION:** Despite being mounted under `/api/admin/` and documented as admin-only, this endpoint has **no** `authenticateToken` or `authorizeRoles` guard. Any unauthenticated request can read scanner state. > ⚠️ **NOT IMPLEMENTED:** The following endpoints do not exist in the codebase: > - `GET /api/admin/settings/confirmation-thresholds/history` — only the current-values `GET /api/admin/settings/confirmation-thresholds` and per-chain `PATCH /api/admin/settings/confirmation-thresholds/:chainId` exist. > - `POST /api/admin/rn/networks/reload` — the network registry cannot be reloaded at runtime via HTTP. > - `POST /api/admin/rn/networks/probe/:chainId` — no per-chain probe endpoint exists. ## Analytics There is no dedicated analytics router. Admin dashboards stitch together: - `GET /api/users/admin/stats` (user metrics) - `GET /api/payment/stats` (payment aggregates — note: `'completed'` status is excluded from `successfulPayments` count) - `GET /api/disputes/statistics` (dispute KPIs) - `GET /api/admin/cleanup/stats` (collection sizes) - `GET /api/payment/shkeeper/webhook-stats` (provider health) - `GET /api/payment/shkeeper/wallet-monitor/status` (chain monitor) ## Related - [[Admin Console Architecture]] - [[Authorization Model]] - [[Error Codes]]