How to set up recurring, automated billing (rent, utilities, memberships, etc.) using the official Numismatics Bank Terminal peripheral — no custom mod required. Everything here works on a stock CC: Tweaked computer next to a Numismatics Bank Terminal.
Full API reference:
NUMISMATICS_API.md(in this folder) A ready-made example implementation ships inauto_billing_example.lua(pure Lua, reference only).
The Core Idea
Numismatics authorized cards are the official automation mechanism. Each authorized card is bound to a sub-account of a player’s bank account. A sub-account has:
- its own authorization UUID
- an authorization type controlling who may spend it:
TRUSTED_PLAYERS— only players on its trust listTRUSTED_AUTOMATION— trusted players and machines/automationANYBODY— anything that holds the card data
- an optional spending limit (hard cap tracked by a
spentcounter)
A computer holding the card’s (accountID, authorizationID) pair can pull
money from that sub-account via the Bank Terminal peripheral’s
bank.transfer(...). Numismatics itself enforces authorization type and
spend limit — your script can’t overspend even if it wants to.
Requirements
- CC: Tweaked computer
- Numismatics Bank Terminal placed adjacent to the computer
- Numismatics config:
getSubAccountsCommand = trueif you want to list sub-account labels programmatically (optional but handy)
Hardware Setup
- Place a Bank Terminal next to the computer.
- Optional: a monitor for status display.
That’s it — the Bank Terminal peripheral handles all bank access. You do NOT need barrels or card readers for billing; the card is only needed once, to read out the account + authorization UUIDs (see below).
Subscriber Setup (what each player does)
- Open their Bank Terminal → SubAccounts tab
- Create a sub-account for the service (e.g. “Server Rent”)
- Set the authorization type to TRUSTED_AUTOMATION (recommended) or ANYBODY
- Optionally set a spending limit — this acts as a hard safety cap
- Create an authorized card bound to that sub-account
- Hand the card to whoever runs the billing computer
The biller reads the pair off the card once (right-clicking the card shows the IDs, or scan it through any system that exposes NBT) and stores:
{ accountID = "<player account uuid>", authorizationID = "<sub-account uuid>" }
Biller Setup (what you do)
- Wrap the terminal:
local bank = peripheral.find("Numismatics_BankTerminal")
- Store subscriber records in a config file (JSON via
textutils). - On your schedule, call transfer for each subscriber.
The Billing Call
-- Pull 100 cogs (6400 spurs) from a subscriber's sub-account to your account
local ok, err = pcall(bank.transfer,
sub.accountID, -- fromAccountID (parent account)
sub.authorizationID, -- fromAuthorizationID (sub-account)
myAccountID, -- toAccountID (your account)
6400) -- amount in spurs
if not ok then
print("Billing failed for " .. (sub.label or sub.accountID) .. ": " .. tostring(err))
end
Useful companion calls:
bank.getBalance(accountID) -- balance in spurs
bank.getMaxAvailableWithdrawal(accountID, authID) -- remaining quota
bank.getSubAccounts(accountID) -- list sub-auth UUIDs (*)
bank.getSubAccountLabel(accountID, authID) -- human-readable label (*)
(*) requires the getSubAccountsCommand config option.
Scheduling
CC: Tweaked computers don’t tick reliably across server restarts, so anchor billing to wall-clock time instead of uptime:
local now = os.epoch("utc") / 1000
if now - state.lastBilled >= 86400 then -- 24h
billAllSubscribers()
state.lastBilled = now
end
os.sleep(30)
Persist state and the subscriber list to disk (textutils.serialiseJSON)
so restarts don’t double-bill anyone.
How the Limit Works
The sub-account limit is a hard cap enforced by Numismatics, tracked by a
monotonic spent counter:
- Limit hit →
transferthrows; the subscriber must reset/raise the limit in their Bank Terminal GUI (or set no limit) - No limit set → effectively capped by the account balance
- Never reset limits from automation — that defeats their purpose
Check getMaxAvailableWithdrawal(accountID, authID) before billing to show
“X remaining” style info instead of relying on failures.
Failure Handling
| Error | Cause | What to do |
|---|---|---|
Insufficient funds | Balance below amount | Retry next cycle |
| Deduction / limit error | Sub-account spent counter maxed | Subscriber resets limit |
Account not found | Account deleted | Remove subscriber |
| Authorization errors | Sub-account deleted | Re-issue card |
Log failures per subscriber and keep going — one bad subscriber shouldn’t block the rest of the cycle.
Security Notes
- Treat stored
(accountID, authorizationID)pairs like cash — anyone who can run Lua on that computer can spend from them - Prefer
TRUSTED_AUTOMATIONoverANYBODYso leaked pairs can’t be used by arbitrary machines - Keep billing amounts at or below what subscribers agreed to; the limit is the real safety net, not your script