-
Notifications
You must be signed in to change notification settings - Fork 30
Description
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 The list method rejects pagination arguments (count/newer_id/older_id) #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.