userId.
Minting (creating reputation from nothing, or destroying it) is service-key-only and lives in @sublay/node.
All hooks are importable from @sublay/react-js, @sublay/react-native, and @sublay/expo.
Requires the reputation bundle on the project. See Bundles and the Reputation model.
Hooks at a glance
There is no Redux store and no provider for grants. Lists are local state held by the wrapper hook, and per-item totals ride along on the items themselves.
Sending a grant
useCreateReputationGrant returns a callable. The sender’s bucket is debited and the recipient’s bucket for the same space is credited; the recipient is notified.
- The sender chooses which of their buckets pays, never where it lands. The reputation always arrives in the recipient’s bucket for the same space. Reputation never crosses between the project-general bucket and a space bucket.
- The target is an annotation. It says what the grant was for, not who gets paid or from which bucket. It doesn’t even have to be authored by the recipient.
409 reputation-grant/insufficient-reputation and nothing moves. A spaceId naming no space rejects earlier still, with 404 reputation-grant/space-not-found. Grant creation is not idempotent — guard your button against double-submits, because a retry moves the points twice.
Showing totals on an item
Ask for the grants summary inline rather than fetching a list you then have to sum. Entities and comments take agrants token in include; chat messages take an includeGrants boolean:
viewerTotal is an amount, not a flag — a user may grant the same item more than once. The server returns a zero-filled summary rather than omitting the key on a project with no grants, so grants being undefined always means “nobody asked for it”.
Listing grants
Use the wrapper for a ready-made paginated list. Exactly one filter shape per query — by recipient, by sender, or by target:summary is only returned on the target shape — it is exactly the block a standalone “who rewarded this” view needs, so you don’t have to fetch the parent item just to print the totals.
Only positive grants come back, and lists are never block-filtered. Negative grants (your app’s moderation deductions) are invisible on every SDK read surface. And unlike entity or comment feeds, grant lists apply no block exclusion — so the amounts you render always add up to the total you render beside them.
Grants in chat
A grant landing on a chat message is broadcast live to everyone in the conversation, the same way message reactions are.ChatProvider handles the message:grant event for you: the message’s grants summary updates in the store and your components re-render.
Load messages with includeGrants: true so each message carries a baseline summary — without it, viewerTotal starts at 0 and only reflects grants seen live in that session.
When users can’t grant directly
A project can switch user-initiated grants off from Settings → SDK in the dashboard. The switch is the project settingsettings.reputationGrants.allowUserInitiated: only an explicit false closes the endpoint to user tokens, an absent key means grants are allowed, and the stored value survives unrelated settings updates so it changes only when that key is explicitly sent. When it’s off, useCreateReputationGrant rejects with 403 reputation-grant/user-grants-disabled, and grants must be routed through your backend with a service key instead — a mediated transfer, which behaves identically to a user grant (same bucket routing, same balance check) but lets you enforce your own rules first: caps, cooldowns, daily limits, eligibility. Sublay imposes none of those itself.

