The clinic queue is the list a clinic’s front desk works from: one row per benefit instance a member is expected to attend for. It spans every benefit type — an insurance policy’s health check and a standalone health checkup queue identically.
The queue tracks the visit, not the entitlement. A benefit instance’s own status (benefit_entities.status) says whether a member is entitled; the queue says where they are in today’s process. They are separate on purpose — see Why not a benefit status.A consumer admits; an operator advances. Rows are created automatically when a benefit instance is created, and moved through the workflow by clinic staff.

Row shape

The workflow

  • CREATED — admitted; the member is expected but has not arrived.
  • IN_PROGRESS — the member has reached the clinic and is being seen.
  • COMPLETED — terminal.
CREATED → COMPLETED directly is allowed, so an operator correcting a row that was never a real visit does not have to click through the check-in step.
The permitted edges are configuration, not code — served per benefit_type and benefit_id, so one clinic can narrow its own workflow without a release. A refused transition returns 400 with CQE_1905.

Admission

There is no request body. Every stored field is read from the benefit instance named in the path, so a caller cannot place a row in another provider’s tenant by naming a different benefit.
Admission is idempotent, and re-admitting never rewinds. The benefit instance’s id is the row’s primary key, so a repeated call returns the existing row unchanged with 200 rather than resetting it — a redelivered admission cannot undo a check-in the operator has already made. Only the first call returns 201.The id is in the path rather than a body because the caller already knows the key: this is an action on a known instance, like POST /mandates/{id}/sync.One consequence: there is one queue entry per benefit instance ever.

Listing

Responses use the standard { data, total, limit, offset } envelope.
A caller scoped to one clinic sees only that clinic’s rows, whatever benefit_provider_id it sends. On a single read, another tenant’s row returns 404, not 403 — a 403 would confirm the id exists.

Advancing a row

Setting the status a row already holds is a no-op, not an error — a retrying caller gets 200 and the unchanged row.

Why not a benefit status

The obvious-looking alternative is a new value on benefit_entities.status. It was considered and rejected for three reasons.
A member who no-shows and returns next week is a second visit against the same entitlement. Encoded as a status, the first visit is overwritten, and “no-showed, then returned” cannot be represented at all.
An insurance policy that is Pending and one that is under Verification both project onto the same benefit status. The ledger literally cannot tell “waiting” from “at the clinic” — the distinction the queue exists to make.
A benefit instance going ACTIVE is one of the two preconditions for autopay. Putting the queue’s workflow on that column would let a receptionist’s action start a payment flow.

Errors