Admin-only.
GET /benefit_entities requires an admin bearer token. There is
no write API — ledger rows are minted server-side, in the same database
transaction as the policy / consultation they describe, so a utilization can
never be recorded without its owning entity (or vice-versa).Row shape
entity_id is polymorphic (it points into two different tables) and so carries
no foreign key. Integrity is guaranteed at write time because the ledger row
is inserted in the same transaction as its owner.Immutable history
A utilization is a historical fact: rows are never updated or deleted, and the table has no status column. Consultations are recorded at initiation — a consultation that later fails upstream still has a ledger row, because the ledger records utilization attempts.Listing
GET /benefit_entities returns the standard paginated envelope
({ data, total, limit, offset }) and supports:
entity_id— narrow to one benefit instance (the utilized policy / consultation id).user_id— scope to a single user (omit to list across all users).entity_type—INSURANCE_POLICYorCONSULTATION.benefit_id— a specific benefit.start_time/end_time— bound results bycreated_at(ISO 8601).sort_on/sort_by— sort (sort_on=created_at,sort_by=asc|desc; defaults to newest first).limit/offset— pagination (limit capped at 100).
Resolving a benefit instance’s tenant
The ledger is the only place a benefit instance’splatform_id is recorded, so
?entity_id= doubles as a point lookup for “which platform was this policy created
under?”.
This matters for the enrollment-form preview
(POST /users/{user_id}/insurance_policies/preview_enrollment_form), which needs a
tenant to decide the fallback address printed on the form when the user has none of
their own. App and platform callers carry the tenant in their token; an admin
does not, and must name one via the x-platform-id header — which the backend
honors only for admin actors. So an admin client resolves it from the ledger
first:
Document downloads need no such dance — they are policy-scoped, so the backend
resolves the tenant from the ledger itself. The preview is the exception because it
is callable before a policy exists (the app’s pre-purchase flow), where there is
no ledger row to read.