Create Reputation Grant
Reputation Grant Endpoints
Create Reputation Grant
Transfer reputation from one user’s bucket to another user’s bucket in the same space
Create Reputation Grant
Transfers reputation between two users. This is a debited transfer: the amount leaves the sender’s bucket and lands in the recipient’s bucket for the same space. Nothing is created — see Mint Reputation Grant for that.
Requires authentication. A user token sends from the token’s own user. A service or master key may name any sender via
Field-level failures are prefixed with the field path, so
A service or master key called the endpoint without naming an
The
The
One answer for both parties, deliberately non-disclosing — and the same answer returned when a block edge exists in either direction.
The target record does not exist — or, for a
Nothing moves. Also the answer when the
Retryable. Two simultaneous transfers from the same bucket can never both succeed against the same balance.
Rate limit: 50 requests per 5 minutes per IP. Exceeding it returns
actingUserId, which is how an app performs a mediated transfer — enforcing its own economic rules before letting the transfer through. Mediated transfers skip the project-level user-grant switch and ignore block relationships; they are otherwise identical to a user grant, including the balance check.
Requires the reputation bundle (both ReputationBuckets and ReputationGrants must be present in the project’s schema).
Body Parameters
string
required
UUID of the user receiving the reputation. Must differ from the sender.
number
required
Whole number from
1 to 2147483647 (the signed 32-bit maximum, which is also the width of a reputation balance). A transfer can never be zero, negative, or fractional, and it can never exceed what the sender holds in the source bucket.string | null
UUID of the space whose bucket pays. Omitted or
null means the project-general bucket. The reputation always lands in the recipient’s bucket for the same space — reputation never crosses between the general bucket and a space bucket.The space is validated before anything moves: an ID that names no space is rejected with 404 reputation-grant/space-not-found, and naming a space on a project without the spaces bundle is rejected with 403 database/tables-not-available.string | null
Free-text note. Trimmed, up to 2000 characters.
object
Arbitrary key-value data. Up to 1 MB. Omit the key when unused —
null is not accepted.string
What the grant is for:
"entity", "comment", or "chat-message". Must be supplied together with targetId. The target is an annotation — it never determines which bucket is used, and it does not have to be authored by the recipient.string
UUID of the rewarded record. Must be supplied together with
targetType, and must exist at the time of granting.string
Service/master key only. The sender — the user reputation is debited from. Spelled
actingUserId rather than userId because this body already names a target user (recipientId). A user token may only name itself.Response
Returns201 with the created ReputationGrant, written with sourceType: "user".
Both balances move: the sender’s bucket and profile total drop by amount, the recipient’s rise by the same. The recipient is notified (a reputation-grant app notification), and a chat-message-targeted grant is broadcast to the conversation as message:grant.
Gating and blocks
- Project setting. The switch is
settings.reputationGrants.allowUserInitiated, flipped from Settings → SDK in the dashboard. Only an explicitfalsecloses 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 the switch is off a user token is rejected with403 reputation-grant/user-grants-disabled; service and master keys still work, so peer transfers remain available when routed through your backend. - Blocks. If either party has blocked the other, a user grant is rejected in both directions — with the same non-disclosing answer as a missing user. Service and master keys ignore block relationships.
- Suspension. A suspended user cannot send a grant, including on the mediated path — a service key naming a suspended
actingUserIdis rejected too. A master key bypasses the check. A suspended user can always receive a grant.
Error Responses
Invalid Body — 400
Invalid Body — 400
error reads "<path>: <message>" — "amount: Invalid input: expected int, received number" for a fractional amount, "recipientId: Invalid UUID format" for a malformed ID. The one whole-body rule has no path and so no prefix: supplying targetType without targetId (or the reverse) returns "targetType and targetId must be supplied together".Self Grant — 400
Self Grant — 400
Missing Sender — 400
Missing Sender — 400
actingUserId.User Grants Disabled — 403
User Grants Disabled — 403
Suspended — 403
Suspended — 403
reason and endDate are null when the suspension carries neither.Tables Not Available — 403
Tables Not Available — 403
reputation bundle is missing — the route names both of its tables, so a project without it is told about both — or the target’s bundle is missing (e.g. a chat-message target without chat), or a spaceId was supplied on a project without spaces. missingTables names exactly what is absent.Space Not Found — 404
Space Not Found — 404
spaceId names no space in this project. Checked before any balance is touched, so nothing moves.User Not Found — 404
User Not Found — 404
Target Not Found — 404
Target Not Found — 404
chat-message target, the sender is not an active member of that conversation. The two cases are byte-identical so a caller holding a message ID cannot probe whether it exists. Mediated transfers are membership-checked on the named sender exactly as user tokens are.Insufficient Reputation — 409
Insufficient Reputation — 409
spaceId names a real space the sender holds no funded bucket in.Conflict — 409
Conflict — 409
429 with a plain-text message and no code.
See also: useCreateReputationGrant · node-sdk · js-sdk
