Admin API
Driftstack's admin API is a small, opt-in surface gated behind
the driftstack_internal_admin scope. It exists so
the Driftstack team can look up customer orders, apply manual
recoveries when an external provider misbehaves, and attach
internal-only operator notes. This page documents what it can
do — so a customer doing security review can verify the scope.
The scope
Every admin endpoint is preHandler-gated on
driftstack_internal_admin. A customer-facing API
key cannot acquire this scope — minting an admin key requires
direct DB-level provisioning (we explicitly do not expose a
"promote to admin" API). The scope only unlocks the routes
listed below; it does not bypass any
customer-facing authentication.
What admin keys cannot do
-
Read or modify another customer's sessions,
recordings, profiles, or
API keys. Those endpoints scope by
account_idon the calling key — there is no admin-impersonation path. - Issue a crypto refund. Crypto payments are non-refundable by policy; there is no admin endpoint that initiates a crypto-side reversal. See /legal/refunds for the binding rules. Stripe refund handling is unchanged and runs through the Stripe dashboard with audit-only records on our side.
- Charge a customer. Stripe + NowPayments are the only money-moving paths and neither is reachable from the admin scope.
Endpoints
Crypto orders
| Endpoint | Purpose |
|---|---|
GET /v1/admin/crypto-orders |
Cross-account list. Filters: status,
search, payment_id,
account_id, created_after /
created_before (V-666.BY). Cursor-paginated
via next_cursor (V-666.AM).
|
GET /v1/admin/crypto-orders.csv | Same filter set, CSV export (up to 1000 rows / call). |
GET /v1/admin/crypto-orders/stats | Per-status counts, paid revenue by currency, avg time-to-paid. |
GET /v1/admin/crypto-orders/idempotency-metrics | Counters for first-write vs replay vs body-mismatch on the customer checkout endpoint (V-666.AP / V-666.AR). |
GET /v1/admin/crypto-orders/pending-age | Histogram of how long current pending orders have been pending — surfaces stuck flows. |
GET /v1/admin/crypto-orders/daily?days=N | Per-day breakdown of (date, status, count) for charts. |
GET /v1/admin/crypto-orders/:order_id | Single-order lookup with the full envelope (including internal note). |
GET /v1/admin/crypto-orders/:order_id/events | Per-order event stream (state transitions + admin actions, append-only). |
POST /v1/admin/crypto-orders/:order_id/apply-ipn | Manually replay a missed NowPayments IPN. Forward-only state machine. |
PATCH /v1/admin/crypto-orders/:order_id/internal-note | Set / clear the admin-only internal note on an order. |
POST /v1/admin/crypto-orders/sweep-expired | Bulk-expire pending orders older than N hours. |
Other admin surfaces
The crypto-orders surface is documented in detail because it sees the most external interest. Other admin routes exist for:
- Account lifecycle (suspend / unsuspend / restore).
- Health probe + incident management for the public status page.
- Cost-monitoring alert overrides.
- Audit-log archive runs.
Each is gated on the same scope and is audit-logged.
Audit logging
Every admin write lands in admin_audit_log with the
acting admin key id, the action, the resource it touched, and
a timestamp. The customer-facing
audit log page documents the
schema. Audit rows are archived to R2 after 90 days (per
ADR-006).
Minting an admin key
For internal staff: drift admin keys create
--scope driftstack_internal_admin from a host with the
DATABASE_URL set. The plaintext token is shown
once + stored as a SHA-256 hash. There is no "self-service
promotion" path; minting an admin key requires database
access.
Disabling an admin key
drift admin keys revoke <key_id>. The key's
revoked_at column is set; the next auth-cache
refresh (≤ 60s) propagates the revocation to all server
replicas.