Skip to main content

beangulp importer for Wise balance statements (statement.json), with a thin SCA-capable API client: idempotent drafts via referenceNumber, conversion-leg merging, fee splitting, closing-balance assertions

Project description

beangulp-wise

beangulp importer for Wise (formerly TransferWise) balance statements, plus a thin, SCA-capable API client to fetch them.

Wise has no official Python SDK, and the community clients are either experimental or AGPL-licensed; the import workflow needs exactly three GET endpoints, so this package owns a ~100-line client instead (beangulp_wise.client.WiseClient).

Design

The importer consumes statement.json files (one per currency balance), not the API directly — fetching writes files to disk first, so every import is auditable, replayable, and testable offline.

  • referenceNumber (CARD-…, TRANSFER-…, CONVERSION-…) is stored as wise_id: metadata and is the idempotency key: extract() skips references already anywhere in the existing ledger. Re-imports are always safe.
  • Payee by detail type: merchant name for card payments, recipient/sender for transfers, description otherwise.
  • totalFees becomes an explicit posting to fees_account — fees stay visible instead of dissolving into the counter leg.
  • payee_rules ((regex, account, flag)) draft the counter leg; unmatched entries keep the ! review flag and the cash leg only.
  • endOfStatementBalance → a balance assertion the day after the interval.
  • Conversions: each leg appears in a different currency's statement, sharing one referenceNumber. merge_conversions(entries) joins them into a single two-currency transaction — the incoming leg priced @@ what left the other balance net of fees, so it balances exactly.

Usage

from beangulp_wise import Importer, merge_conversions

importer = Importer(
    {"EUR": "Assets:Wise:EUR", "USD": "Assets:Wise:USD"},
    fees_account="Expenses:BankFees:Wise",
    holder="My GmbH",                       # a token may see several profiles
    payee_rules=((r"cloudflare", "Expenses:IT:Hosting", "!"),),
)
entries = merge_conversions(
    importer.extract("statement-eur.json", existing=ledger_entries)
    + importer.extract("statement-usd.json", existing=ledger_entries)
)

Fetching statements (SCA)

Statement endpoints are protected by Strong Customer Authentication: Wise answers 403 with a one-time token in the x-2fa-approval header, which must be signed (RSA-SHA256, PKCS#1 v1.5) with a private key whose public half is registered on the Wise account (Settings → API tokens → Manage public keys).

from beangulp_wise import WiseClient

client = WiseClient(token, private_key_pem=open("private.pem", "rb").read())
pid = client.profile_id("My GmbH")
for balance in client.balances(pid):
    statement = client.balance_statement(
        pid, balance["id"], balance["currency"],
        "2026-07-01T00:00:00.000Z", "2026-07-31T23:59:59.999Z",
    )

cryptography is an optional dependency (beangulp-wise[sca]) — importing statement files works without it.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

beangulp_wise-0.1.1.tar.gz (17.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

beangulp_wise-0.1.1-py3-none-any.whl (15.9 kB view details)

Uploaded Python 3

File details

Details for the file beangulp_wise-0.1.1.tar.gz.

File metadata

  • Download URL: beangulp_wise-0.1.1.tar.gz
  • Upload date:
  • Size: 17.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for beangulp_wise-0.1.1.tar.gz
Algorithm Hash digest
SHA256 508f51045b8f44ae072a777ad1cf15c5a84555e6bfd0ef40a5ace1ed66f349cb
MD5 326201d19bc4e8e09599086c3c7717ff
BLAKE2b-256 7a381b5264d6719000f679fba76d27f6cb8d0a91b8dbef559a3297a7a300cce5

See more details on using hashes here.

Provenance

The following attestation bundles were made for beangulp_wise-0.1.1.tar.gz:

Publisher: publish.yaml on sealambda/quints

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file beangulp_wise-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: beangulp_wise-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 15.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for beangulp_wise-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 62b0ab375532114460b1c51c15bf613a375875c359ed35d8ff6bf191ab642543
MD5 9d0da90f18cade782d9e691a3f3ef338
BLAKE2b-256 0999bd2097c5d41e9faf785a5bf160185f29534142dd3498832ec6efea8be177

See more details on using hashes here.

Provenance

The following attestation bundles were made for beangulp_wise-0.1.1-py3-none-any.whl:

Publisher: publish.yaml on sealambda/quints

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page