API ReferenceBilling Metrics (server-to-server pull)

Billing Metrics API

EmbayLMS runs platform billing on direct Stripe Billing: Stripe is the billing engine, and the LMS owns the definition of what to bill. This endpoint exposes each tenant’s current billable metrics, computed live per call so a read is always current.

This is a server-to-server endpoint — not part of the tenant-facing public API.

This endpoint is not the billing path. The LMS sets the Stripe subscription quantity itself, ahead of each renewal, from the same figures — Stripe has no way to pull them. This API is an integration surface for an external billing orchestrator that wants the same numbers (reporting, a future alternative billing model). Reading it changes nothing; the LMS remains what pushes the quantity to Stripe.

Note: although live, this endpoint is intentionally excluded from the public OpenAPI spec at /api/v1/docs. It authenticates with a static platform Bearer secret issued by Embay, not a tenant API key, and is only for the external billing orchestrator — this page is its canonical reference.

Finding the tenant

Call with the EmbayLMS tenant id. The Stripe Customer carries metadata.embaylms_tenant_id, so the orchestrator can map a Stripe customer/subscription back to the tenant id to pull with.

Endpoint

GET /api/v1/billing/metrics?tenantId={uuid}

embaylms_tenant_id is accepted as an alias for tenantId.

Authentication

Authorization: Bearer <platform-metrics-secret>

A single platform secret, issued by Embay to the orchestrator. Missing or mismatched ⇒ 401. The check is constant-time.

Response 200

{
  "data": {
    "tenantId": "eaf926b4-7bec-440a-9083-7e75ad8a193b",
    "slug": "acme",
    "status": "active",
    "activeUsersInPeriod": 1,
    "activeUsersThisMonth": 1,
    "licensedUsers": 2,
    "periodStart": "2026-07-15T00:00:00.000Z",
    "asOf": "2026-06-24T23:54:53.089Z"
  },
  "meta": null,
  "error": null
}
FieldMeaning
activeUsersInPeriodBillable quantity (default) — users who logged in at least once during the tenant’s current billing period (active, not deleted).
activeUsersThisMonthDeprecated alias of activeUsersInPeriod, same value. Kept so existing consumers do not break on the rename; the field never tracked a calendar month again after that change. Prefer activeUsersInPeriod.
periodStartInclusive start of the window the count was taken over — the subscription’s current_period_start, or the first of the calendar month when Stripe has not reported a period yet.
licensedUsersProvisioned active accounts (seats available).
asOfServer timestamp when the counts were computed.

New metrics: each billable metric is a discrete field, so a metric added later appears as a new field (there is no metric-type enum). The orchestrator decides which field a given subscription bills on.

Status codes

CodeWhen
200Authorized; metrics returned.
400tenantId (or embaylms_tenant_id) missing.
401Missing or invalid Bearer token, or the endpoint is not enabled on this environment.
404No tenant with that id.
409The tenant is never billed — a demo, sandbox or the platform Academy tenant — so there is no billable quantity to report. The error names the kind.

Troubleshooting

  • Always 401 — the orchestrator is sending a different secret from the one Embay issued, or the endpoint has not been enabled on that environment. Contact Embay to confirm.
  • 404 for a known tenant — confirm the tenant id (or the Stripe customer’s embaylms_tenant_id metadata) matches an EmbayLMS tenant.
  • Counts look low — only users who logged in during the current billing period count as active; provisioned-but-never-logged-in users do not. Check periodStart in the response to see which window was used — a tenant renewing mid-month is counted from its renewal date, not the 1st.