Swarmz

Top up credits

Add purchased credits to a tenant. Purely additive, idempotent on your key, and billed on assign. Addressed by tenant_id.

POSThttps://api.swarmz.net/functions/v1/platform-topup

Adds purchased credits to a tenant. The operation is purely additive — it increments the tenant's topup_credits balance via the platform_topup_credits RPC and never replaces or resets existing balances. Address the tenant by tenant_id — the id returned by create — or fall back to your external_ref. Supply exactly one identifier.

Billed on assign

Top-up credits are billed to your platform account at the moment they are assigned to the tenant, not when the tenant later spends them. A successful top-up is a chargeable event — which is exactly why the idempotency_key is required (see Idempotency).

Parameters

Prop

Type

Request

curl -X POST https://api.swarmz.net/functions/v1/platform-topup \
  -H "Authorization: Bearer sk_live_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6" \
  -H "Content-Type: application/json" \
  -d '{
    "tenant_id": "aa7d7fae-0386-4d8a-b977-72f856eac242",
    "amount": 100,
    "idempotency_key": "whmcs:1234:topup-2026-05-23-0001"
  }'
const res = await fetch('https://api.swarmz.net/functions/v1/platform-topup', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer sk_live_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    tenant_id: 'aa7d7fae-0386-4d8a-b977-72f856eac242',
    amount: 100,
    idempotency_key: 'whmcs:1234:topup-2026-05-23-0001',
  }),
});

const data = await res.json();
import requests

res = requests.post(
    "https://api.swarmz.net/functions/v1/platform-topup",
    headers={"Authorization": "Bearer sk_live_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"},
    json={
        "tenant_id": "aa7d7fae-0386-4d8a-b977-72f856eac242",
        "amount": 100,
        "idempotency_key": "whmcs:1234:topup-2026-05-23-0001",
    },
)
data = res.json()

Response

After the credit is applied the function re-reads workspace_billing and returns a fresh snapshot:

{
  "ok": true,
  "balances": {
    "included_credits": 0,
    "included_credits_used": 0,
    "rollover_credits": 0,
    "rollover_credits_used": 0,
    "topup_credits": 100,
    "daily_bonus_limit": 50,
    "daily_bonus_used": 0
  }
}
FieldTypeDescription
okbooleanAlways true on success.
balancesobjectFresh snapshot of the tenant's workspace_billing row. {} if the row could not be re-read (the top-up still applied).
balances.included_creditsnumberMonthly grant for the current cycle.
balances.included_credits_usednumberMonthly grant consumed this cycle.
balances.rollover_creditsnumberCredits carried over from prior cycles.
balances.rollover_credits_usednumberRollover consumed this cycle.
balances.topup_creditsnumberThe purchased-credit balance this endpoint increments.
balances.daily_bonus_limitnumberDaily free-credit allowance.
balances.daily_bonus_usednumberDaily free credits used today.

Which fields matter for a tenant

For platform tenants, topup_credits, daily_bonus_limit, and daily_bonus_used are the meaningful fields. The included_* / rollover_* fields are returned for completeness and are driven by the plan + plan-refresh cycle, not by this endpoint.

Errors

StatuserrorreasonWhen
400missing_fieldstenant_id or external_ref requiredNeither identifier supplied
400invalid_amountamount must be a positive finite numberamount is non-positive, non-finite, or not a number
400missing_fieldsidempotency_key requiredidempotency_key absent or not a string
401unauthorizedmissing_bearer / invalid_key / account_disabledSee Authentication
404tenant_not_foundNo tenant matched the identifier under your account
405method_not_allowedAnything other than POST
409suspendedThe tenant is suspended
410terminatedThe tenant has been terminated
409tenant_not_activethe client_statusThe tenant exists but is in some other non-active state
429rate_limitedper_key / per_ipRate limit hit — see Rate limits
500topup_failedRPC messageThe platform_topup_credits RPC failed server-side; safe to retry with the same idempotency_key
500internal_errorUnhandled server error; safe to retry with the same key

Status checks run in order

The function checks suspended (409) → terminated (410) → any other non-active state (409 tenant_not_active) before touching credits, so a non-active tenant is never charged.

Idempotency

Top-up is idempotent on idempotency_key. A retry with the same key is a no-op at the RPC level — it does not add the amount again and does not bill again — and the endpoint still returns the current balances. Always reuse the same key when retrying a top-up after a network error or a 500. See Idempotency.

Notes

A suspended tenant rejects top-ups

Topping up a suspended tenant returns 409 suspended. Queue the top-up and replay it after unsuspend. Because the idempotency key dedupes the charge, the queued retry is safe — re-sending it once the tenant is active applies the credit (and the bill) exactly once.

  • Address the tenant by tenant_id from create; external_ref is the fallback.
  • Top-up is for purchased credits only. The monthly grant and rollover are owned by the plan and the plan-refresh cycle, not by this endpoint.

On this page