Swarmz

Account billing summary

The owner-facing billing snapshot for your own platform account — period usage, the upcoming invoice, the card on file, and recent invoices. Supabase user-JWT authed; not a host API call.

GEThttps://api.swarmz.net/functions/v1/platform-billing-summary

Returns the consolidated billing snapshot for your own platform (reseller) account — the data the account-level billing page renders in one shot: period usage, the upcoming Stripe invoice, the card on file, and recent invoices.

This is an owner dashboard endpoint — not a host API call

Unlike the rest of the Platform API, platform-billing-summary is not authenticated with your sk_live_ key and takes no tenant_id / external_ref / period parameters. It authenticates the account owner via their Supabase user JWT and resolves the one active account they own (or admin-member). It exists to power your billing page, not to drive a WHMCS integration. For host-facing usage roll-ups by tenant, use usage.

Authentication

Send the owner's Supabase user JWT as a Bearer token — not a sk_live_ API key:

Authorization: Bearer <supabase-user-jwt>

The account is resolved from the caller's identity: the single active account they own, falling back to an active admin membership. There are no body parameters — the endpoint reads everything from the authenticated user.

Request

platform-billing-summary accepts GET (the natural verb, and what the dashboard proxy forwards) or POST. There is no request body.

curl https://api.swarmz.net/functions/v1/platform-billing-summary \
  -H "Authorization: Bearer <supabase-user-jwt>"
const res = await fetch('https://api.swarmz.net/functions/v1/platform-billing-summary', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${supabaseUserJwt}`,
  },
});

const data = await res.json();
import requests

res = requests.get(
    "https://api.swarmz.net/functions/v1/platform-billing-summary",
    headers={"Authorization": f"Bearer {supabase_user_jwt}"},
)
data = res.json()

Response

{
  "ok": true,
  "account": { "id": "<uuid>", "name": "...", "slug": "...", "email": "owner@example.com" },
  "usage": {
    "credits_used": 0,
    "usd_credits": 0,
    "cloud_usd": 0,
    "period": { "from": "<ISO>", "to": "<ISO>", "label": "current_month" },
    "by_workspace": [
      { "workspace_id": "<uuid>", "credits_used": 0, "usd_credits": 0, "cloud_usd": 0 }
    ]
  },
  "upcoming": {
    "amount_due_cents": 0,
    "currency": "usd",
    "period_end": 1234567890,
    "next_attempt": 1234567890
  },
  "card": {
    "brand": "visa",
    "last4": "0000",
    "exp_month": 12,
    "exp_year": 2030
  },
  "card_on_file": true,
  "billing": {
    "company": "...",
    "email": "...",
    "address": { "line1": "...", "city": "...", "country": "..." },
    "vat": "..."
  },
  "invoices": [
    {
      "id": "<uuid>",
      "stripe_invoice_id": "in_...",
      "status": "paid",
      "amount_due_cents": 0,
      "amount_paid_cents": 0,
      "currency": "usd",
      "period_start": "<ISO>",
      "period_end": "<ISO>",
      "hosted_invoice_url": "https://...",
      "paid_at": "<ISO>",
      "created_at": "<ISO>"
    }
  ]
}

Field meanings:

FieldMeaning
accountYour account identity. email is the owner's auth email (billing is bound to it).
usageThe same current-period roll-up the usage endpoint computes — shared code, so the two never drift. period.label is current_month.
upcomingThe Stripe upcoming/preview invoice for your subscription: amount_due_cents, currency, period_end (next bill date), next_attempt. null when there's no subscription or no card. Stripe timestamps are Unix seconds.
upcoming_errorPresent only when the Stripe preview fetch failed — a string reason. The rest of the summary still returns; upcoming degrades to null instead of failing the call.
cardThe default payment method: brand, last4, exp_month, exp_year. null when no card is attached.
card_on_fileBoolean — whether a card is recorded on the account.
billingSaved billing identity from Stripe: company, email, address, vat. null when not yet set.
invoices[]Up to 24 recent rows from platform_invoices, newest first.

upcoming may carry upcoming_error

A Stripe hiccup never 500s the summary. When the preview invoice fetch fails, the response still returns ok: true with upcoming: null and an upcoming_error string describing what went wrong (e.g. stripe_not_configured: ...). Treat upcoming as best-effort.

Errors

StatuserrorreasonWhen
401unauthorizedmissing_bearerNo Bearer token supplied
401unauthorizedinvalid_tokenThe user JWT failed verification
403forbiddenno_active_accountThe caller owns no active account and has no active admin membership
405method_not_allowedAnything other than GET or POST
500internal_errorUnexpected server-side failure; safe to retry
500usage_read_failedRPC reasonThe usage roll-up failed server-side
500invoices_read_failedDB messageThe invoice read failed server-side

Idempotency

Not applicable — billing summary is a pure read. Safe to call as often as you like. See Idempotency.

Notes

Pair with platform-usage for host integrations

billing-summary is the owner's view of their own account. To report usage per tenant from your WHMCS integration (key-authed, scoped to a tenant_id), use usage instead.

On this page