The wallet balance, what is available or committed, and the latest wallet loads.
Check how much is on your Spendesk wallet, how much is still available to spend, what is already committed, and which loads arrived recently.
Wallet Acme France (EUR)
Balance 98,900.00
Available to spend 97,300.86
Allocated on cards 1,599.14
Scheduled transfers 0.00 (invoices 0.00, expense claims 0.00)
Wallet loads, last 30 days: 1
2026-09-12 wireTransfer 100,000.00 EURScopes: wallet-summary:read, wallet-load:read. Set-up: Running the recipes.
With Postman
In the Settlements and wallet folder:
- Get Wallet Summary — no parameter.
totalAmountis the balance,totalAvailableAmountwhat remains to spend,allocatedOnCardswhat is set aside on cards, andscheduledTransfersAmountthe invoice and expense-claim payments already scheduled. Amounts are in cents. - Get Wallet Loads — set
fromto the start of the period as a date and time, for example2026-09-01T00:00:00.000Z. Each load has itsamount,type(wireTransferorcard) andcreatedAt.
With an AI assistant
What is our Spendesk wallet balance, how much is still available, and which wallet loads did we receive in the last 30 days?
With a script
Save it as treasury.py, then run python3 treasury.py — or python3 treasury.py 90 for the loads of the last 90 days.
"""Treasury check: wallet balance, what is committed, and the latest wallet loads.
Usage: python3 treasury.py [DAYS] (loads of the last N days, default 30)
Needs SPENDESK_CLIENT_ID and SPENDESK_CLIENT_SECRET; SPENDESK_COMPANY_ID with an organisation-level key.
Scopes: wallet-summary:read, wallet-load:read.
"""
import base64, datetime as dt, json, os, sys, urllib.parse, urllib.request
BASE = os.environ.get("SPENDESK_BASE_URL", "https://public-api.spendesk.com")
COMPANY = os.environ.get("SPENDESK_COMPANY_ID")
def token():
creds = base64.b64encode(f"{os.environ['SPENDESK_CLIENT_ID']}:{os.environ['SPENDESK_CLIENT_SECRET']}".encode()).decode()
req = urllib.request.Request(BASE + "/v1/auth/token", data=b"grant_type=client_credentials",
headers={"Authorization": "Basic " + creds, "Content-Type": "application/x-www-form-urlencoded"})
return json.load(urllib.request.urlopen(req))["access_token"]
TOKEN = token()
def api(method, path, query=None, body=None):
url = BASE + path + ("?" + urllib.parse.urlencode(query, doseq=True) if query else "")
headers = {"Authorization": "Bearer " + TOKEN, "Content-Type": "application/json"}
if COMPANY:
headers["X-Company-Id"] = COMPANY
req = urllib.request.Request(url, method=method, headers=headers, data=json.dumps(body).encode() if body else None)
return json.load(urllib.request.urlopen(req))
# 1. The wallet: amounts are in cents, divide by 100.
w = api("GET", "/v1/wallet-summary")
cur = w["currency"]
print(f"Wallet {w['name']} ({cur})")
print(f" Balance {w['totalAmount'] / 100:>14,.2f}")
print(f" Available to spend {w['totalAvailableAmount'] / 100:>14,.2f}")
print(f" Allocated on cards {w['allocatedOnCards']['totalAllocatedAmount'] / 100:>14,.2f}")
print(f" Scheduled transfers {w['scheduledTransfersAmount']['totalScheduledTransferAmount'] / 100:>14,.2f}"
f" (invoices {w['scheduledTransfersAmount']['scheduledInvoicesAmount'] / 100:,.2f},"
f" expense claims {w['scheduledTransfersAmount']['scheduledExpenseClaimsAmount'] / 100:,.2f})")
# 2. Wallet loads of the period, 30 per page.
days = int(sys.argv[1]) if len(sys.argv) > 1 else 30
since = (dt.datetime.now(dt.timezone.utc) - dt.timedelta(days=days)).strftime("%Y-%m-%dT%H:%M:%S.000Z")
loads, page = [], 1
while True:
result = api("GET", "/v1/wallet-loads", {"from": since, "page": page, "pageSize": 30})
loads += result["data"]
if page * 30 >= result["meta"]["pagination"]["total"]:
break
page += 1
print(f"\nWallet loads, last {days} days: {len(loads)}")
for load in sorted(loads, key=lambda x: x["createdAt"], reverse=True):
print(f" {load['createdAt'][:10]} {load['type']:<13} {load['amount'] / 100:>14,.2f} {load['currency']}")Good to know
- One wallet per company: with an organisation-level key, run it once per company, changing
SPENDESK_COMPANY_ID. fromandtotake a date and time (2026-09-01T00:00:00.000Z), not a date alone.- Wallet loads come 30 per page at most: the script reads every page.
The requests are Get Wallet Summary and Get Wallet Loads.