Listing company exports via SDK returns no items, but direct REST call works when user id is explicit
I’m integrating the official Python SDK to list and export customer statements (MT940/PDF) across both personal and company monetary accounts, and I’ve run into issues that seem to be SDK-specific:
Listing company exports via SDK returns no items, but direct REST call works when user id is explicit Context With a personal API key that has access to company accounts, I can:
- list accounts (personal + company),
- create and download statement exports for those accounts,
- but cannot list existing exports for company-owned accounts via the SDK’s list; it returns an empty set.
Workaround that succeeds
- If I call the REST endpoint using the owning user’s id explicitly, I get the expected results.
- Path: user/{OWNER_USER_ID}/monetary-account/{ACCOUNT_ID}/customer-statement
- Query params (e.g., count=50) work as expected.
Evidence from verbose logs (ids and names anonymized)
- [debug] SDK list signature mismatch: ExportStatementApiObject.list() got an unexpected keyword argument 'count'. is related to #180
[debug] Listing exports for account id={PERSON_ACCOUNT_ID}, owner='{PERSON_NAME}', ownerUserId={PERSON_USER_ID}, ownerType=Unknown, params={'count': 50, 'newer_id': None, 'older_id': None} [debug] SDK list signature mismatch: ExportStatementApiObject.list() got an unexpected keyword argument 'count'. Retrying with required-only param -> parsed 52 items.
[debug] Listing exports for account id={COMPANY_ACCOUNT_ID_A}, owner='{COMPANY_NAME_A}', ownerUserId={COMPANY_USER_ID_A}, ownerType=Unknown, params={'count': 50, 'newer_id': None, 'older_id': None} [debug] SDK list signature mismatch: ExportStatementApiObject.list() got an unexpected keyword argument 'count'. Retrying with required-only param -> empty set. [debug] Fallback GET user/{COMPANY_USER_ID_A}/monetary-account/{COMPANY_ACCOUNT_ID_A}/customer-statement params={'count': '50'} -> bytes=17225 [debug] Fallback parsed 12 items for acc_id={COMPANY_ACCOUNT_ID_A}
[debug] Listing exports for account id={COMPANY_ACCOUNT_ID_B}, owner='{COMPANY_NAME_B}', ownerUserId={COMPANY_USER_ID_B}, ownerType=Unknown, params={'count': 50, 'newer_id': None, 'older_id': None} [debug] SDK list signature mismatch: ExportStatementApiObject.list() got an unexpected keyword argument 'count'. Retrying with required-only param. [debug] Fallback GET user/{COMPANY_USER_ID_B}/monetary-account/{COMPANY_ACCOUNT_ID_B}/customer-statement params={'count': '50'} -> bytes=26727 [debug] Fallback parsed 19 items for acc_id={COMPANY_ACCOUNT_ID_B}
Interpretation
- The SDK list implementation seems to bind to the current session’s user id (personal), then attempts GET user/{SESSION_USER_ID}/monetary-account/{ACCOUNT_ID}/customer-statement. If the monetary account is owned by a company (a different user id), that call returns empty results rather than the company’s actual statements.
- When I direct the call to user/{OWNER_USER_ID}/monetary-account/{ACCOUNT_ID}/customer-statement, I get the correct items immediately.
Suggested fixes
- Make listing resilient for company accounts by either:
- Auto-detecting the correct owner user id from the monetary_account_id before building the path, or
- Exposing an overload or alternate method that accepts user_id as an explicit parameter, e.g., ExportStatementApiObject.list_for_user(user_id, monetary_account_id, ...).
- Ensure consistent JSON shape mapping in the Python SDK. The REST response for listing is typically: {"Response": [{"CustomerStatementExport": {...}}, ...]} The Python SDK sometimes exposes "ExportStatement," while the raw API uses "CustomerStatementExport." Aligning/normalizing this in the SDK payload models would help.
Minimal repro (Python)
- Environment:
- Python 3.11 on macOS
- bunq Python SDK installed from PyPI
- Sketch:
from bunq.sdk.context.api_context import ApiContext, ApiEnvironmentType
from bunq.sdk.context.bunq_context import BunqContext
from bunq.sdk.model.generated import endpoint as bunq_endpoint
from bunq.sdk.http.api_client import ApiClient
# Setup
api_context = ApiContext.create(ApiEnvironmentType.PRODUCTION, "<API_KEY>", "exporter")
BunqContext.load_api_context(api_context)
# Enumerate accounts (includes company accounts)
accounts = bunq_endpoint.MonetaryAccountApiObject.list().value
# For each account:
# resolve concrete subtype + id (e.g., account_id)
acc_id = <ACCOUNT_ID>
# 1) SDK list: pagination args not accepted -> TypeError
# bunq_endpoint.ExportStatementApiObject.list(monetary_account_id=acc_id, count=50) # raises TypeError
# 2) SDK list without pagination: returns items for personal, empty for company-owned accounts
res = bunq_endpoint.ExportStatementApiObject.list(monetary_account_id=acc_id).value # empty for company
# 3) Direct HTTP call using owner user id works
owner_uid = <OWNER_USER_ID>
api_client = ApiClient(api_context) # reuse session
raw = api_client.get(f"user/{owner_uid}/monetary-account/{acc_id}/customer-statement", {"count": "50"}, {})
data = raw.body_bytes # JSON -> Response list contains CustomerStatementExport items
Direct REST illustration
- GET https://api.bunq.com/v1/user/{OWNER_USER_ID}/monetary-account/{ACCOUNT_ID}/customer-statement?count=50
- Auth: existing session/headers from SDK context
- Returns JSON with the expected list of statement exports.