Grant Credits (Admin)
Sets an account’s credit balance, and records who set it and why. Requires the authenticated account to be a Recoup admin.
Absolute, not a delta. remaining_credits is the balance the account is left holding, whatever it held before — the outcome never depends on the balance at the moment the request lands. The prior balance comes back as previous_credits for the record. There is deliberately no add/subtract variant.
Every grant is audited. reason is required and must be non-empty. The grant is stored against the acting admin’s account ID and is readable afterwards in the grants array of GET /api/admins/credits/events.
A grant expires after one month — plan for it. Credit balances are refilled to the plan total by a monthly reset that runs lazily on the next read of GET /api/accounts/{id}/credits, once the underlying row is more than a month old. Setting a balance here restarts that clock, so the balance holds until expires_at (one month after granted_at) and is then silently overwritten on the first balance read after it — with 9,999 for an account carrying an active Stripe subscription, and 333 for every other account, including one with no Stripe customer at all. Nothing warns the account holder, and nothing warns you. If the headroom needs to outlive a month, grant it again; if the account should stay funded indefinitely, put it on a pro subscription rather than granting.
Authorizations
Your Recoup API key. Learn more.
Body
The account to set, the balance to leave it at, and why
UUID of the account whose balance is being set. Must be an existing account — an unknown UUID is a 404, not a silent no-op.
The balance to leave the account holding, in credits (1 credit = 1 US cent). Absolute, not a delta. Zero is allowed — it is how an account is deliberately zeroed out. Negative values are rejected with a 400, even though ordinary usage can overdraw a balance below zero on its own.
x >= 0Why the grant was made, in plain language — e.g. Trial headroom for the Aug 12 label demo. Required and non-empty (a whitespace-only string is rejected): this is the field that makes a grant distinguishable from a Stripe top-up or a monthly reset when someone asks months later. Stored verbatim and returned by the events endpoint.
1Response
Balance set and the grant recorded
Status of the request
success UUID of the recorded grant row. Matches the id of the corresponding entry in the grants array of GET /api/admins/credits/events.
UUID of the account whose balance was set (echoes the request)
The balance the account now holds — the value supplied in the request
The balance immediately before the grant. Null when the account had no credits row at all and one was created by this request.
The reason recorded with the grant (echoes the request)
UUID of the admin account that made the grant, resolved from the credentials on the request. Never taken from the body.
When the grant was recorded
When the monthly reset becomes eligible to overwrite this balance — one month after granted_at, clamped to the last day of the target month when that month is shorter (a grant on Jan 31 expires Feb 28, not Mar 3). The overwrite is lazy, not scheduled: it happens on the first read of the account's balance at or after this time, so the granted balance can outlive expires_at indefinitely if nothing reads it. Treat it as the point after which the balance is no longer guaranteed — it is deliberately never later than the moment the reset actually becomes eligible, so it can under-promise by up to a day but never over-promise.
