← Back to docs
api·Updated May 2, 2026

Admin API

REST API reference for user plan management, credit operations, and audit logging. Authenticated via X-Admin-Key header.

The Admin API provides operator-level access to user plans and credits. All endpoints require the X-Admin-Key header and are excluded from Clerk session authentication.

Authentication

All /api/admin/* endpoints require:

X-Admin-Key: <ADMIN_API_KEY>

The key is set via the ADMIN_API_KEY environment variable on the backend. If the header is missing or incorrect, the API returns 403 Forbidden.

Endpoints

GET /api/admin/users/:userId/plan

Retrieve a user's current plan, credit balance, and tier.

Response:

{
  "ok": true,
  "userId": "user_2xExampleAbcDeFgHiJkLmNoPqR",
  "plan": {
    "id": "plan",
    "userId": "user_2xExampleAbcDeFgHiJkLmNoPqR",
    "type": "plan",
    "tier": "free",
    "credits_balance": 5000,
    "credits_monthly": 0,
    "reset_date": "2026-06-02T04:20:10.082Z"
  }
}

POST /api/admin/users/:userId/plan

Set a user's tier. This resets their credit balance to the tier's initial allotment.

Request body:

{ "tier": "free" }

Valid tiers: free, starter, pro, enterprise

Response:

{
  "ok": true,
  "userId": "user_2xExampleAbcDeFgHiJkLmNoPqR",
  "tier": "free",
  "creditsGranted": 5000
}

POST /api/admin/users/:userId/credits

Add or remove credits from a user's balance.

Request body:

{ "amount": 5000, "reason": "courtesy_grant" }
  • amount — non-zero number (positive to grant, negative to deduct)
  • reason — optional string for the audit log

Response:

{
  "ok": true,
  "userId": "user_2xExampleAbcDeFgHiJkLmNoPqR",
  "amount": 5000,
  "newBalance": 10000
}

GET /api/admin/users/:userId/credit-events

View a user's credit audit log.

Query parameters:

  • limit — max events to return (default 50, max 200)

Response:

{
  "ok": true,
  "userId": "user_2xExampleAbcDeFgHiJkLmNoPqR",
  "events": [
    {
      "id": "evt_1714600000000_abc123",
      "timestamp": "2026-05-02T04:20:10.082Z",
      "amount": 5000,
      "reason": "plan_reset",
      "balance_after": 5000
    }
  ]
}

Error Responses

All errors follow a consistent format:

{ "error": "description of what went wrong" }
StatusMeaning
400Invalid request body (missing tier, zero amount, etc.)
403Missing or invalid X-Admin-Key header
500Internal server error (database failure, etc.)

Usage from cURL

# View plan
curl -s -H "X-Admin-Key: $ADMIN_API_KEY" \
  "https://app.arrowflow.app/api/admin/users/$USER_ID/plan"

# Reset credits
curl -s -X POST \
  -H "X-Admin-Key: $ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tier":"free"}' \
  "https://app.arrowflow.app/api/admin/users/$USER_ID/plan"

# Add credits
curl -s -X POST \
  -H "X-Admin-Key: $ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount":5000,"reason":"courtesy_grant"}' \
  "https://app.arrowflow.app/api/admin/users/$USER_ID/credits"

See Also

  • MCP CLIarrowflow-mcp admin commands wrap these endpoints for direct terminal use
  • Admin MCP Serverarrowflow-mcp serve admin exposes these as MCP tools for AI agents