Admin API
Admin endpoints require a valid JWT obtained from POST /api/v1/admin/login. The JWT is set as an httpOnly cookie after login.
Authentication
POST /api/v1/admin/login
Content-Type: application/json
{"password": "your-admin-password"}Response sets paywarden_admin cookie (httpOnly, Secure in production). All subsequent admin requests include this cookie automatically in browsers. For API usage, extract the cookie manually.
POST /api/v1/admin/logout
Cookie: paywarden_admin=<jwt>Dashboard stats
GET /api/v1/admin/stats
Cookie: paywarden_admin=<jwt>Response 200:
{
"orders": {
"total": 1420,
"pending": 12,
"confirmed_today": 38,
"expired_today": 4
},
"revenue": {
"today": "3820.50",
"this_month": "48200.00",
"total": "284500.00",
"currency": "USDT"
},
"merchants": {
"total": 5,
"active": 5
},
"wallet": {
"hot_wallet_address": "TXxx...",
"trx_balance": "450.00",
"usdt_balance": "120.50"
}
}Daily revenue chart
GET /api/v1/admin/stats/daily?days=30
Cookie: paywarden_admin=<jwt>Response 200:
{
"data": [
{ "date": "2025-01-01", "revenue": "1200.00", "orders": 14 },
{ "date": "2025-01-02", "revenue": "980.50", "orders": 11 }
]
}Merchants
List merchants
GET /api/v1/admin/merchants
Cookie: paywarden_admin=<jwt>Response 200:
{
"data": [
{
"id": "merch_abc123",
"name": "My Shop",
"api_key_prefix": "pw_live_xxxx",
"webhook_url": "https://myshop.com/webhooks/paywarden",
"orders_total": 142,
"revenue_total": "14200.00",
"created_at": "2025-01-01T00:00:00Z",
"active": true
}
],
"total": 5
}Create merchant
POST /api/v1/admin/merchants
Cookie: paywarden_admin=<jwt>
Content-Type: application/json
{
"name": "New Shop",
"webhook_url": "https://newshop.com/webhooks"
}Response 201:
{
"id": "merch_xyz789",
"name": "New Shop",
"api_key": "pw_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"api_key_prefix": "pw_live_xxxx",
"webhook_url": "https://newshop.com/webhooks",
"created_at": "2025-01-01T00:00:00Z"
}One-time display
The api_key is shown only on creation. It cannot be retrieved again. Store it immediately.
Rotate API key
POST /api/v1/admin/merchants/:id/rotate-key
Cookie: paywarden_admin=<jwt>Generates a new API key. The old key is immediately invalidated.
Response 200:
{
"id": "merch_abc123",
"api_key": "pw_live_new_key_here...",
"api_key_prefix": "pw_live_newk"
}Suspend / reactivate merchant
PATCH /api/v1/admin/merchants/:id
Cookie: paywarden_admin=<jwt>
Content-Type: application/json
{"active": false}Suspended merchants cannot create new orders. Existing orders continue processing.
Orders (admin view)
GET /api/v1/admin/orders?page=1&limit=20&status=failed&merchant_id=merch_abc
Cookie: paywarden_admin=<jwt>Returns orders across all merchants. Same schema as the merchant-scoped GET /api/v1/payments but includes merchant_id and merchant_name fields.
Wallet
GET /api/v1/admin/wallet
Cookie: paywarden_admin=<jwt>Response 200:
{
"hot_wallet_address": "TXxx...",
"trx_balance": "450.00",
"usdt_balance": "120.50",
"xpub": "xpub6Cx...",
"next_address_index": 1420,
"pending_sweeps": 3
}Error codes
| Code | Meaning |
|---|---|
ADMIN_UNAUTHORIZED | Missing or expired admin JWT |
MERCHANT_NOT_FOUND | Merchant ID does not exist |
MERCHANT_NAME_TAKEN | Merchant name already in use |
KEY_ROTATION_FAILED | Failed to generate new API key |