---
id: w8/m2/t003
title: REST adapter — GET /v1/usage (documented bex extension)
worker: worker8
status: todo
estimate: 30m
depends_on: [w8/m2/t001]
---

## Objective

Expose the core verb as `GET /v1/usage?ownerId=…&period=…` — a **deliberate bex extension**: Render's public REST API has no billing/usage endpoints (verified by the w1/m13 parity audit against Render's OpenAPI), so this is the same class as bex's API-key management extra. Render-style JSON conventions, `ownerId` = the `tea-…` workspace id consistent with the owners surface (w6/m2).

## Context

- REST adapters live per-feature (e.g. `internal/apps/rest.go`); follow that registration pattern.
- `period` defaults to the current month; accept `YYYY-MM` for past months (returns empty until history exists — no error).
- Error shapes: same 401/403/503 semantics as the other verbs (503 when the store is unset, mirroring env-vars-without-OpenBao).

## Steps

1. Implement the handler + routing in `internal/usage/rest.go`.
2. Map the core result to Render-vocabulary JSON (computeSeconds by tier, egressBytes, buildSeconds — final names settled against t002 so REST and GraphQL agree).
3. Handler tests: happy path, bad `period`, cross-workspace denial, store-unset 503.

## Files

- `lego/backend/internal/usage/rest.go` (+ test)

## Acceptance criteria

- [ ] `curl` against a dev server returns the same numbers t002's GraphQL reports for the same workspace/month.
- [ ] Documented as a bex extension in t005's docs, never presented as a Render-compatible endpoint.

## Out of scope

- Pagination (aggregates are small); CSV export.
