Skip to content
FIGGSHIELD

Admin metrics

Staff-only platform metrics: GET /api/admin/metrics/, its full response shape, and the 403 admin_required returned to non-staff accounts.

View as Markdown

Figgshield exposes one staff-only endpoint for platform metrics. It backs the internal admin dashboard (run locally, not part of the public app) and is not part of the normal customer API surface — ordinary accounts never reach it.

Staff accounts are created out-of-band, through the Django admin or shell; there is no signup or upgrade path to staff. Every ordinary account carries is_staff: false in its user object; staff accounts carry is_staff: true.

Platform metrics

GET /api/admin/metrics/ — requires a staff account. Authenticate with a staff session cookie or an API key belonging to a staff account.

curl https://api.figgshield.ai/api/admin/metrics/ \
  -H "Authorization: Bearer $FIGGSHIELD_API_KEY"

A non-staff caller — even a perfectly valid, authenticated one — receives 403 with the machine code admin_required:

{ "error": "admin_required", "detail": "This endpoint requires a staff account." }

The response aggregates users, subscriptions, revenue, provider costs and margins, plus 30-day daily and per-model breakdowns. All monetary amounts are integer cents.

{
  "generated_at": "2026-07-06T09:00:00Z",
  "users": {
    "total": 4120,
    "new_30d": 318,
    "onboarding": { "profile": 44, "plan": 61, "complete": 4015 }
  },
  "subscriptions": {
    "active_total": 2870,
    "cancel_at_period_end": 63,
    "by_plan": [
      { "slug": "starter", "name": "Starter", "count": 980, "yearly_cents": 14400 },
      { "slug": "pro", "name": "Pro", "count": 1080, "yearly_cents": 34800 },
      { "slug": "studio", "name": "Studio", "count": 170, "yearly_cents": 90000 }
    ]
  },
  "revenue": {
    "run_rate_yearly_cents": 89078400,
    "effective_monthly_cents": 7423200,
    "topups_30d_cents": 512000
  },
  "costs": {
    "provider_30d_cents": 2140000,
    "per_active_user_monthly_cents": 745
  },
  "margins": {
    "monthly_revenue_cents": 7423200,
    "monthly_cost_cents": 2140000,
    "gross_margin_pct": 71.2
  },
  "daily": [
    { "date": "2026-07-01", "signups": 11, "new_subscriptions": 7, "credits_used": 24310, "provider_cost_cents": 71200 }
  ],
  "by_model": [
    { "model": "Kling", "generations": 1820, "credits": 63700, "provider_cost_cents": 637000 },
    { "model": "Nano Banana 2", "generations": 5140, "credits": 41120, "provider_cost_cents": 174760 }
  ]
}

Response fields

GroupFields
generated_atWhen these figures were computed.
userstotal, new_30d, and an onboarding funnel counting accounts at each step (profile, plan, complete).
subscriptionsactive_total, cancel_at_period_end, and by_plan — per-plan active counts with each plan’s yearly_cents (12 × the monthly sticker).
revenuerun_rate_yearly_cents, effective_monthly_cents (the run-rate ÷ 12), and topups_30d_cents.
costsprovider_30d_cents and per_active_user_monthly_cents.
marginsmonthly_revenue_cents, monthly_cost_cents, and gross_margin_pctnull when monthly revenue is 0.
dailyThe last 30 days, one entry per day: signups, new_subscriptions, credits_used, provider_cost_cents.
by_modelThe last 30 days per model (Kling, Nano Banana 2): generations, credits, provider_cost_cents.

Provider cost is the best available estimate: the actual per-call cost where the provider reports it, otherwise a per-model admin-set estimate multiplied by the number of calls. The GET /api/models/ public schema never exposes these internal cost figures.