Refresh a tenant's billing cycle
Rollover unused credits and reset the monthly allowance at a billing-cycle boundary. Idempotent per (tenant, cycle anchor).
https://api.swarmz.net/functions/v1/platform-plan-refreshPerforms a host-driven monthly reset on a tenant. Called from your renewal or cycle hook (for example, WHMCS InvoicePaid). It resets included_credits to the tenant's entitlements.monthly_credits, rolls over any unused included_credits according to entitlements.rollover_months (0 = none, 1 = one cycle, 2 = two cycles), and resets the daily-free and monthly-cap counters.
Address the tenant by tenant_id or external_ref — supply exactly one.
Parameters
Prop
Type
Request
curl -X POST https://api.swarmz.net/functions/v1/platform-plan-refresh \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"external_ref": "whmcs:1234",
"cycle_anchor": "2026-06-01T00:00:00.000Z"
}'const res = await fetch('https://api.swarmz.net/functions/v1/platform-plan-refresh', {
method: 'POST',
headers: {
Authorization: 'Bearer sk_live_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({
external_ref: 'whmcs:1234',
cycle_anchor: '2026-06-01T00:00:00.000Z',
}),
});
const data = await res.json();import requests
res = requests.post(
"https://api.swarmz.net/functions/v1/platform-plan-refresh",
headers={"Authorization": "Bearer sk_live_..."},
json={
"external_ref": "whmcs:1234",
"cycle_anchor": "2026-06-01T00:00:00.000Z",
},
)
data = res.json()Response
A fresh refresh returns the new balances and the new cycle start:
{
"ok": true,
"result": {
"success": true,
"included_credits": 500,
"rollover_credits": 120,
"rollover_months": 1,
"expired_previous_rollover": 0,
"billing_cycle_start": "2026-06-01T00:00:00.000Z"
}
}If the same (tenant, cycle_anchor) has already been refreshed, the call short-circuits:
{
"ok": true,
"result": {
"success": true,
"skipped": true,
"reason": "already_refreshed_for_cycle",
"billing_cycle_start": "2026-06-01T00:00:00.000Z"
}
}Errors
| Status | error | reason | When |
|---|---|---|---|
| 400 | missing_fields | tenant_id or external_ref required | Neither identifier supplied |
| 400 | invalid_cycle_anchor | cycle_anchor must be an ISO date | cycle_anchor is not a parseable ISO date |
| 401 | unauthorized | — | See Authentication |
| 404 | tenant_not_found | — | No tenant matched the identifier under your account |
| 405 | method_not_allowed | — | Anything other than POST |
| 410 | terminated | — | The tenant has been terminated |
| 429 | rate_limited | per_key / per_ip | Rate limit hit — see Rate limits |
| 500 | refresh_failed | RPC message | Refresh failed server-side; safe to retry |
Idempotency
Refresh is idempotent on (tenant, cycle_anchor). A second call with the same anchor is a no-op and returns skipped: true — credits are never double-granted, and rollover is never applied twice for the same cycle. See Idempotency.
Notes
The host owns the billing cycle
Pass the cycle_anchor that matches the service's next-due-date in your
billing system. A renewal cron can then safely replay this call — duplicate
hits with the same anchor short-circuit, and the first successful refresh per
cycle is the one that lands.
This endpoint is limited to 60 requests/min per key and 120/min per IP. See Rate limits.
Change a tenant's plan
Patch a tenant's entitlements and mirror its daily credit allowance. Send the full entitlements object you want — it replaces within the keys provided.
Top up credits
Add purchased credits to a tenant. Purely additive, idempotent on your key, and never replaces existing balances.