Swarmz

Refresh a tenant's billing cycle

Rollover unused credits and reset the monthly allowance at a billing-cycle boundary. Idempotent per (tenant, cycle anchor).

POSThttps://api.swarmz.net/functions/v1/platform-plan-refresh

Performs 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

StatuserrorreasonWhen
400missing_fieldstenant_id or external_ref requiredNeither identifier supplied
400invalid_cycle_anchorcycle_anchor must be an ISO datecycle_anchor is not a parseable ISO date
401unauthorizedSee Authentication
404tenant_not_foundNo tenant matched the identifier under your account
405method_not_allowedAnything other than POST
410terminatedThe tenant has been terminated
429rate_limitedper_key / per_ipRate limit hit — see Rate limits
500refresh_failedRPC messageRefresh 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.

On this page