List workspace members and invitations
const url = 'http://localhost:8080/v1/members';const options = {method: 'GET', headers: {cookie: 'hardcount_session=<hardcount_session>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url http://localhost:8080/v1/members \ --cookie hardcount_session=<hardcount_session>Dashboard-session only (403 for API keys — membership is a human
act with a human actor). Members are every user attached to the
tenant; invitations carry a server-derived status
(pending/accepted/revoked/expired). No RBAC yet: role is
recorded but every member holds the full permission set. ADR-081.
Authorizations
Section titled “Authorizations”Responses
Section titled “Responses”Members + invitations
object
object
object
Recorded for the future role split; not enforced (every member holds the full permission set).
Server-derived; treat as authoritative.
Example
{ "invitations": [ { "id": "hc_minv_1a2b3c4d5e6f7890", "status": "pending" } ]}Caller is not a dashboard session
object
object
One of invalid_request_error, authentication_error,
rate_limit_error or api_error. Every error the API
answers has this shape, including an unknown path (404,
code route_not_found) and a method the path does not take
(405, code method_not_allowed, with an Allow header).
The few exceptions are listed in docs/api-surface.md.
The request field the error is about. Sent only when the error
names one. A request body may hold only the fields its
operation lists, spelled and cased as listed: any other
field, or one the server sets (such as id), is refused
with 422 and param naming it. An operation with no request body lists no fields: send
no body, {} or null. The Stripe and Postmark webhooks and
the LiteLLM callback take their sender’s body as it comes.
Example
{ "error": { "type": "invalid_request_error" }}