Files
nick-doc/03 - API Reference/Admin API.md

13 KiB
Raw Blame History

title, tags
title tags
Admin API
api
admin
reference

Admin API

Last updated: 2026-05-30 — break-glass endpoints added, scanner/status auth fixed, reload/probe routes now implemented, confirmation threshold history implemented, resolver role added

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' unless explicitly noted otherwise. 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).

[!note] Resolver role The resolver role was added (commit fce8a19). Resolvers have access to the dispute-triage endpoints (assign, status, resolve, statistics) only. All other admin endpoints remain admin-only.

User management

See full descriptions in User API.

Path note: The frontend uses /api/users/admin/* (plural — legacy userRoutes). The singular /api/user/admin/* group (new userController) is also mounted (app.ts). Since backend 14c231e (v2.8.50) the plural group delegates toggle-status and dependencies to the new controller so every frontend call routes. Prefer /api/users/admin/* for user-management calls.

Endpoint Action
POST /api/users/admin/create Create user with role/status
DELETE /api/users/admin/:userId Soft delete user — sets status='deleted' (admins cannot delete each other)
PATCH /api/users/admin/:userId/status Activate / suspend
PATCH /api/users/admin/:userId/toggle-status Flip active flag
PATCH /api/users/admin/:userId/role Change role
GET /api/users/admin/list Paginated directory + stats
GET /api/users/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 (legacy route — uses 8-digit codes)

Verification code length: The endpoint POST /api/users/admin/:userId/resend-verification is served by the legacy userRoutes and generates 8-digit codes. The new userController generates 6-digit codes and is reached via a different path. Both coexist; the legacy route takes precedence for this path.

FIXED (frontend d7a2a86 / 6fe1328, v2.8.5051): the old PUT-verb and status-value mismatches are gone — updateUserStatus sends PATCH with { isActive: boolean } (the field the legacy plural route reads).

Soft delete + email release (backend 378f8f6, v2.8.51): DELETE /api/users/admin/:userId soft-deletes (sets status='deleted') and releases the email (renamed to deleted_<legacyId>_<email>) so the address can be reused. Create/register also lazily free emails still held by accounts deleted before this fix. Soft-deleted users are excluded from the admin list and all stats (backend 14c231e).

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/….)

Derived destinations & sweep

Frontend page: /dashboard/admin/derived-destinations. Backend registers 7 endpoints under /api/payment/derived-destinations/* with admin auth.

Endpoint Action
GET /api/payment/derived-destinations List all derived destination addresses
POST /api/payment/derived-destinations/sweep/trigger Trigger a sweep across all destinations
POST /api/payment/derived-destinations/sweep/trigger/:id Trigger sweep for a single destination
GET /api/payment/derived-destinations/sweep/cron/status Get sweep cron job status
POST /api/payment/derived-destinations/sweep/cron/start Start the sweep cron job
POST /api/payment/derived-destinations/sweep/cron/stop Stop the sweep cron job
GET /api/payment/derived-destinations/sweep/history Sweep history log

Frontend action functions: getDerivedDestinations, triggerSweep, triggerSingleSweep, getSweepCronStatus, startSweepCron, stopSweepCron.

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. 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:

{
  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 AMN Pay Scanner. Proxies to AMN_SCANNER_URL/scanner/status. Auth required: Bearer JWT (admin) — authenticateToken + authorizeRoles('admin') were added in commit 1d881c5. The previously documented unauthenticated access gap (ISSUE-006) is closed.

POST /api/admin/scanner/webhooks/retry

Description: Trigger a retry of failed/pending scanner webhooks. Auth required: Bearer JWT (admin) Request body: { intentId?: string } — omit to retry all pending.

Settings

AML settings

⚠️ RUNTIME-ONLY PERSISTENCE: PATCH /api/admin/settings/aml updates process.env at runtime only. Changes are lost on server restart. There is no frontend page for these endpoints.

Endpoint Auth Action
GET /api/admin/settings/aml admin Read current AML settings
PATCH /api/admin/settings/aml admin Update AML settings (runtime only — not persisted to disk or DB)

AML providers available:

  • Chainalysis — cloud API provider (requires CHAINALYSIS_API_KEY). Enabled via AML_PROVIDER=chainalysis.
  • OFAC SDN local — downloads the US Treasury SDN XML list once per 24 hours and checks addresses locally. No API key required. Enabled via AML_PROVIDER=ofac. Added in commit 31343d1 (Task #10). List is fetched from OFAC_SDN_URL (defaults to https://www.treasury.gov/ofac/downloads/sdn.xml).

The active provider is selected at startup via AML_PROVIDER. PATCH /api/admin/settings/aml can switch the provider at runtime but the change is not persisted.

Confirmation thresholds

Frontend page exists. Endpoints require admin auth.

Endpoint Action
GET /api/admin/settings/confirmation-thresholds Get current confirmation thresholds for all chains
PATCH /api/admin/settings/confirmation-thresholds/:chainId Update threshold for a specific chain
GET /api/admin/settings/confirmation-thresholds/history Last 50 threshold change events (populated with changedBy user email/name)

History route: GET /api/admin/settings/confirmation-thresholds/history is now implemented (commit 27fb15a). It reads from the ConfigSettingHistory collection, keyed as confirmation_threshold:<chainId>.

Break-glass (Trezor bypass)

Three endpoints manage the break-glass mode, which disables the Trezor safekeeping requirement for escrow release/refund for up to 1 hour. All changes fire a Telegram alert.

Endpoint Action
GET /api/admin/settings/break-glass Read current break-glass status (active, expiresAt, activatedBy)
POST /api/admin/settings/break-glass Activate break-glass for 1 hour
DELETE /api/admin/settings/break-glass Cancel break-glass before it expires

[!warning] In-memory state Break-glass state is stored in-memory only (breakGlassRoutes.ts). A server restart always clears it, which is intentional. The isBreakGlassActive() helper is exported and consumed by the Trezor safekeeping middleware.

Payments awaiting confirmation

Frontend page exists.

Endpoint Auth Action
GET /api/admin/payments/awaiting-confirmation admin List payments pending blockchain confirmation

RN network registry

Frontend page exists.

Endpoint Auth Action
GET /api/admin/rn/networks admin List all registered RN networks
POST /api/admin/rn/networks/reload admin Reload chain + token registries from disk (no restart needed)
POST /api/admin/rn/networks/probe/:chainId admin On-demand on-chain probe: RPC reachability, proxy bytecode, dummy-call validity

All three routes are implemented (commit 5681abf). Previous docs listed reload and probe as not implemented.

Blog admin

Backend registers 5 blog admin endpoints, all guarded by authorizeRoles('admin'). Frontend has action functions calling each.

Endpoint Action
GET /api/blog/admin/posts List all blog posts (admin view, includes drafts)
POST /api/blog/posts Create a new blog post
GET /api/blog/admin/posts/:id Get a single blog post (admin view)
PUT /api/blog/posts/:id Update a blog post
DELETE /api/blog/posts/:id Delete a blog post

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)