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.0.tar.gz (16.6 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.0-py3-none-any.whl (15.2 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for beangulp_wise-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4fec6ce811578a412abbac91507b8376cbbe4268aa3838dd1a7202d66572e400
MD5 986afab2fae2cdca66c374b3530268c5
BLAKE2b-256 02fece6fb268f68349850b72a753772a33c7252afec351e0c4919406ac875536

See more details on using hashes here.

Provenance

The following attestation bundles were made for beangulp_wise-0.1.0.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.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for beangulp_wise-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 db0f238ddec2eb4eac7768ee0192f8bf4377543e3b0a18fc6f3e73cb9a646e8c
MD5 caab8d835eec4ebf21b265310a851fec
BLAKE2b-256 10af38fbdcaf013662bcdc22126204851dfded73b2ae31ee74f97ca5e8e4bb9a

See more details on using hashes here.

Provenance

The following attestation bundles were made for beangulp_wise-0.1.0-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