Skip to content

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

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

http
POST /api/v1/admin/logout
Cookie: paywarden_admin=<jwt>

Dashboard stats

http
GET /api/v1/admin/stats
Cookie: paywarden_admin=<jwt>

Response 200:

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

http
GET /api/v1/admin/stats/daily?days=30
Cookie: paywarden_admin=<jwt>

Response 200:

json
{
  "data": [
    { "date": "2025-01-01", "revenue": "1200.00", "orders": 14 },
    { "date": "2025-01-02", "revenue": "980.50", "orders": 11 }
  ]
}

Merchants

List merchants

http
GET /api/v1/admin/merchants
Cookie: paywarden_admin=<jwt>

Response 200:

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

http
POST /api/v1/admin/merchants
Cookie: paywarden_admin=<jwt>
Content-Type: application/json

{
  "name": "New Shop",
  "webhook_url": "https://newshop.com/webhooks"
}

Response 201:

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

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

json
{
  "id": "merch_abc123",
  "api_key": "pw_live_new_key_here...",
  "api_key_prefix": "pw_live_newk"
}

Suspend / reactivate merchant

http
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)

http
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

http
GET /api/v1/admin/wallet
Cookie: paywarden_admin=<jwt>

Response 200:

json
{
  "hot_wallet_address": "TXxx...",
  "trx_balance": "450.00",
  "usdt_balance": "120.50",
  "xpub": "xpub6Cx...",
  "next_address_index": 1420,
  "pending_sweeps": 3
}

Error codes

CodeMeaning
ADMIN_UNAUTHORIZEDMissing or expired admin JWT
MERCHANT_NOT_FOUNDMerchant ID does not exist
MERCHANT_NAME_TAKENMerchant name already in use
KEY_ROTATION_FAILEDFailed to generate new API key

Released under the BSL 1.1 License.