The approved supplier invoices to pay in the next days, overdue ones first, with the total still due per currency.
See which approved supplier invoices you have to pay in the next seven days — and which are already overdue — with the amount still due and the total per currency.
2026-09-26 (overdue) Office Supplies Ltd FA-2026-3391 1,944.00 EUR
2026-10-02 Cloud Hosting Inc INV-88412 2,490.00 EUR
2 invoices due by 2026-10-06: 4,434.00 EURScopes: experimental:invoice:read, and user:read to find your company ID with a company-level key. Set-up: Running the recipes.
ExperimentalInvoice endpoints are experimental: their scope is granted on request, and they may still change. See Versioning & Deprecation.
With Postman
In the Invoices and intakes folder, open List invoices and set these query parameters — change the date to seven days from today:
| Parameter | Value |
|---|---|
dueBefore | 2026-10-06 |
paymentStatus | unpaid, and a second paymentStatus row with partiallyPaid |
approvalStatus | approved |
sortBy | dueDate |
sort | asc |
Each invoice shows its supplier.name, invoiceNumber, dueDate and amountDue — what remains to pay, in cents. The company ID in the path comes from your environment's companyId; with a company-level key, Get Users shows it as companyId on every user.
With an AI assistant
Which approved supplier invoices are due in the next 7 days or already overdue? Give me the supplier, the amount still due and the due date, and the total per currency.
With a script
Save it as due_invoices.py, then run python3 due_invoices.py — or python3 due_invoices.py 14 for the next 14 days.
"""List the supplier invoices to pay in the next N days (default 7), overdue ones included.
Usage: python3 due_invoices.py [DAYS]
Needs SPENDESK_CLIENT_ID and SPENDESK_CLIENT_SECRET; SPENDESK_COMPANY_ID with an organisation-level key.
Scopes: experimental:invoice:read, user:read (to find your company ID with a company-level key).
"""
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 company ID goes in the path of v2 endpoints. A company-level key reads it from any user.
company = COMPANY or api("GET", "/v1/users", {"pageSize": 1})["data"][0]["companyId"]
# 2. Approved invoices not fully paid, due before the cutoff, earliest first.
days = int(sys.argv[1]) if len(sys.argv) > 1 else 7
cutoff = dt.date.today() + dt.timedelta(days=days)
query = {"dueBefore": str(cutoff), "paymentStatus": ["unpaid", "partiallyPaid"], "approvalStatus": ["approved"],
"sortBy": "dueDate", "sort": "asc", "limit": 100}
invoices, cursor = [], None
while True:
page = api("GET", f"/v2/companies/{company}/invoices", dict(query, **({"cursor": cursor} if cursor else {})))
invoices += page["data"]
cursor = page["meta"]["pagination"]["nextCursor"]
if not cursor:
break
# 3. Print them, then the total still due per currency. Amounts are in cents: divide by 100.
totals = {}
for inv in invoices:
late = " (overdue)" if inv["dueDate"] < str(dt.date.today()) else ""
print(f"{inv['dueDate']}{late} {inv['supplier']['name']:<30} {inv['invoiceNumber']:<20} "
f"{inv['amountDue'] / 100:>12,.2f} {inv['currency']}")
totals[inv["currency"]] = totals.get(inv["currency"], 0) + inv["amountDue"]
print(f"\n{len(invoices)} invoices due by {cutoff}:",
", ".join(f"{amount / 100:,.2f} {currency}" for currency, amount in sorted(totals.items())) or "nothing")Good to know
- Only approved invoices are listed. Remove the
approvalStatusfilter to also see those still waiting for approval. - Partially paid invoices are included, with only what remains in
amountDue. - Overdue invoices are included:
dueBeforehas no lower bound. AdddueAfterwith today's date to leave them out. - Several companies: with an organisation-level key, run it once per company, changing
SPENDESK_COMPANY_ID.
The request is List invoices; the company in the path works as described in Organisation-level access.