makky-acb-api 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ include README.md
@@ -0,0 +1,140 @@
1
+ Metadata-Version: 2.4
2
+ Name: makky-acb-api
3
+ Version: 0.1.0
4
+ Summary: Unofficial Python client for ACB account balances and transaction history
5
+ Author: Makky
6
+ Maintainer: Makky
7
+ Project-URL: Homepage, https://github.com/Makky/ACB-API
8
+ Project-URL: Repository, https://github.com/Makky/ACB-API
9
+ Project-URL: Issues, https://github.com/Makky/ACB-API/issues
10
+ Keywords: acb,banking,api,transactions,payments
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Intended Audience :: Developers
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ Requires-Dist: requests>=2.31.0
23
+ Requires-Dist: python-dotenv>=1.0.0
24
+
25
+ # makky-acb-api
26
+
27
+ **πŸ‡ΊπŸ‡Έ English** | [πŸ‡»πŸ‡³ TiαΊΏng Việt](README_VI.md)
28
+
29
+ Unofficial Python client for ACB account balances and transaction history, packaged for local installation and future PyPI publication.
30
+
31
+ ## Features
32
+
33
+ - Authenticate with ACB using username and password
34
+ - Fetch balances for payment accounts
35
+ - Retrieve recent transaction history for a selected account
36
+ - Use as a Python library or from a CLI command
37
+
38
+ ## Installation
39
+
40
+ ### Local development install
41
+
42
+ ```bash
43
+ pip install -r requirements.txt
44
+ pip install -e .
45
+ ```
46
+
47
+ ### After publication to PyPI
48
+
49
+ ```bash
50
+ pip install makky-acb-api
51
+ ```
52
+
53
+ ## Environment variables
54
+
55
+ Create a `.env` file in the project root:
56
+
57
+ ```env
58
+ ACB_USERNAME=your_username
59
+ ACB_PASSWORD=your_password
60
+ ```
61
+
62
+ > [!WARNING]
63
+ > This project uses an unofficial ACB API. Protect your credentials and use it at your own risk.
64
+
65
+ ## Python usage
66
+
67
+ ```python
68
+ from acb_api import ACBClient
69
+
70
+ client = ACBClient(username="your_username", password="your_password")
71
+ balances = client.get_balances()
72
+ print(balances)
73
+
74
+ account = balances["balances"][0]["accountNumber"]
75
+ transactions = client.get_transactions(rows=5, account_number=account)
76
+ print(transactions)
77
+ ```
78
+
79
+ ## CLI usage
80
+
81
+ After `pip install -e .`, run:
82
+
83
+ ```bash
84
+ acb-api --action all --rows 5
85
+ ```
86
+
87
+ Other examples:
88
+
89
+ ```bash
90
+ acb-api --action balances
91
+ acb-api --action transactions --account 19527581 --rows 10
92
+ acb-api --action all --debug
93
+ ```
94
+
95
+ ## Local demo script
96
+
97
+ For backward-compatible local testing:
98
+
99
+ ```bash
100
+ python main.py
101
+ ```
102
+
103
+ ## Project structure
104
+
105
+ ```text
106
+ ACB-API/
107
+ β”œβ”€β”€ src/acb_api/
108
+ β”‚ β”œβ”€β”€ __init__.py
109
+ β”‚ β”œβ”€β”€ cli.py
110
+ β”‚ β”œβ”€β”€ client.py
111
+ β”‚ β”œβ”€β”€ config.py
112
+ β”‚ β”œβ”€β”€ exceptions.py
113
+ β”‚ └── models.py
114
+ β”œβ”€β”€ main.py
115
+ β”œβ”€β”€ pyproject.toml
116
+ └── README.md
117
+ ```
118
+
119
+ ## Packaging notes
120
+
121
+ - Distribution/package name: `makky-acb-api`
122
+ - Import package name: `acb_api`
123
+ - Author / maintainer: `Makky`
124
+
125
+ To build distributable artifacts locally:
126
+
127
+ ```bash
128
+ python -m build
129
+ ```
130
+
131
+ ## Credits
132
+
133
+ This packaged version is maintained by **Makky**.
134
+
135
+ Inspired by earlier community work around ACB unofficial integrations, including:
136
+ - [anhnmt/ACB](https://github.com/anhnmt/ACB)
137
+
138
+ ## Disclaimer
139
+
140
+ This is an unofficial client and is not affiliated with ACB. APIs, headers, and authentication flows may change without notice. Use at your own risk.
@@ -0,0 +1,116 @@
1
+ # makky-acb-api
2
+
3
+ **πŸ‡ΊπŸ‡Έ English** | [πŸ‡»πŸ‡³ TiαΊΏng Việt](README_VI.md)
4
+
5
+ Unofficial Python client for ACB account balances and transaction history, packaged for local installation and future PyPI publication.
6
+
7
+ ## Features
8
+
9
+ - Authenticate with ACB using username and password
10
+ - Fetch balances for payment accounts
11
+ - Retrieve recent transaction history for a selected account
12
+ - Use as a Python library or from a CLI command
13
+
14
+ ## Installation
15
+
16
+ ### Local development install
17
+
18
+ ```bash
19
+ pip install -r requirements.txt
20
+ pip install -e .
21
+ ```
22
+
23
+ ### After publication to PyPI
24
+
25
+ ```bash
26
+ pip install makky-acb-api
27
+ ```
28
+
29
+ ## Environment variables
30
+
31
+ Create a `.env` file in the project root:
32
+
33
+ ```env
34
+ ACB_USERNAME=your_username
35
+ ACB_PASSWORD=your_password
36
+ ```
37
+
38
+ > [!WARNING]
39
+ > This project uses an unofficial ACB API. Protect your credentials and use it at your own risk.
40
+
41
+ ## Python usage
42
+
43
+ ```python
44
+ from acb_api import ACBClient
45
+
46
+ client = ACBClient(username="your_username", password="your_password")
47
+ balances = client.get_balances()
48
+ print(balances)
49
+
50
+ account = balances["balances"][0]["accountNumber"]
51
+ transactions = client.get_transactions(rows=5, account_number=account)
52
+ print(transactions)
53
+ ```
54
+
55
+ ## CLI usage
56
+
57
+ After `pip install -e .`, run:
58
+
59
+ ```bash
60
+ acb-api --action all --rows 5
61
+ ```
62
+
63
+ Other examples:
64
+
65
+ ```bash
66
+ acb-api --action balances
67
+ acb-api --action transactions --account 19527581 --rows 10
68
+ acb-api --action all --debug
69
+ ```
70
+
71
+ ## Local demo script
72
+
73
+ For backward-compatible local testing:
74
+
75
+ ```bash
76
+ python main.py
77
+ ```
78
+
79
+ ## Project structure
80
+
81
+ ```text
82
+ ACB-API/
83
+ β”œβ”€β”€ src/acb_api/
84
+ β”‚ β”œβ”€β”€ __init__.py
85
+ β”‚ β”œβ”€β”€ cli.py
86
+ β”‚ β”œβ”€β”€ client.py
87
+ β”‚ β”œβ”€β”€ config.py
88
+ β”‚ β”œβ”€β”€ exceptions.py
89
+ β”‚ └── models.py
90
+ β”œβ”€β”€ main.py
91
+ β”œβ”€β”€ pyproject.toml
92
+ └── README.md
93
+ ```
94
+
95
+ ## Packaging notes
96
+
97
+ - Distribution/package name: `makky-acb-api`
98
+ - Import package name: `acb_api`
99
+ - Author / maintainer: `Makky`
100
+
101
+ To build distributable artifacts locally:
102
+
103
+ ```bash
104
+ python -m build
105
+ ```
106
+
107
+ ## Credits
108
+
109
+ This packaged version is maintained by **Makky**.
110
+
111
+ Inspired by earlier community work around ACB unofficial integrations, including:
112
+ - [anhnmt/ACB](https://github.com/anhnmt/ACB)
113
+
114
+ ## Disclaimer
115
+
116
+ This is an unofficial client and is not affiliated with ACB. APIs, headers, and authentication flows may change without notice. Use at your own risk.
@@ -0,0 +1,47 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "makky-acb-api"
7
+ version = "0.1.0"
8
+ description = "Unofficial Python client for ACB account balances and transaction history"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ authors = [
12
+ { name = "Makky" }
13
+ ]
14
+ maintainers = [
15
+ { name = "Makky" }
16
+ ]
17
+ dependencies = [
18
+ "requests>=2.31.0",
19
+ "python-dotenv>=1.0.0"
20
+ ]
21
+ keywords = ["acb", "banking", "api", "transactions", "payments"]
22
+ classifiers = [
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3 :: Only",
25
+ "Programming Language :: Python :: 3.9",
26
+ "Programming Language :: Python :: 3.10",
27
+ "Programming Language :: Python :: 3.11",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Programming Language :: Python :: 3.13",
30
+ "Intended Audience :: Developers",
31
+ "Topic :: Software Development :: Libraries :: Python Modules"
32
+ ]
33
+
34
+ [project.urls]
35
+ Homepage = "https://github.com/Makky/ACB-API"
36
+ Repository = "https://github.com/Makky/ACB-API"
37
+ Issues = "https://github.com/Makky/ACB-API/issues"
38
+
39
+ [project.scripts]
40
+ acb-api = "acb_api.cli:main"
41
+
42
+ [tool.setuptools]
43
+ package-dir = {"" = "src"}
44
+ include-package-data = true
45
+
46
+ [tool.setuptools.packages.find]
47
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,4 @@
1
+ from .client import ACB, ACBClient
2
+
3
+ __all__ = ["ACB", "ACBClient"]
4
+ __version__ = "0.1.0"
@@ -0,0 +1,69 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ import os
6
+ from typing import Optional
7
+
8
+ from dotenv import load_dotenv
9
+
10
+ from .client import ACBClient
11
+ from .exceptions import ACBError
12
+
13
+
14
+ def build_parser() -> argparse.ArgumentParser:
15
+ parser = argparse.ArgumentParser(description="Unofficial ACB API CLI")
16
+ parser.add_argument("--username", help="ACB username")
17
+ parser.add_argument("--password", help="ACB password")
18
+ parser.add_argument("--rows", type=int, default=5, help="Number of transactions to fetch")
19
+ parser.add_argument("--account", help="Account number to fetch transactions for")
20
+ parser.add_argument(
21
+ "--action",
22
+ choices=["balances", "transactions", "all"],
23
+ default="all",
24
+ help="Operation to perform",
25
+ )
26
+ parser.add_argument("--debug", action="store_true", help="Enable verbose HTTP debug output")
27
+ return parser
28
+
29
+
30
+ def resolve_credentials(username: Optional[str], password: Optional[str]) -> tuple[str, str]:
31
+ load_dotenv()
32
+ final_username = username or os.getenv("ACB_USERNAME")
33
+ final_password = password or os.getenv("ACB_PASSWORD")
34
+
35
+ if not final_username or not final_password:
36
+ raise ValueError("Missing credentials. Provide --username/--password or set ACB_USERNAME and ACB_PASSWORD.")
37
+
38
+ return final_username, final_password
39
+
40
+
41
+ def main() -> int:
42
+ parser = build_parser()
43
+ args = parser.parse_args()
44
+
45
+ try:
46
+ username, password = resolve_credentials(args.username, args.password)
47
+ client = ACBClient(username=username, password=password, debug=args.debug)
48
+
49
+ if args.action in {"balances", "all"}:
50
+ balances = client.get_balances()
51
+ print(json.dumps({"balances": balances["balances"]}, indent=2, ensure_ascii=False))
52
+
53
+ if args.action in {"transactions", "all"}:
54
+ account = args.account or client.get_first_account_number()
55
+ if not account:
56
+ print("No account available for transaction lookup.")
57
+ return 0
58
+
59
+ transactions = client.get_transactions(rows=args.rows, account_number=account)
60
+ print(json.dumps({"account": account, "transactions": transactions}, indent=2, ensure_ascii=False))
61
+
62
+ return 0
63
+ except (ValueError, ACBError) as exc:
64
+ print(f"Error: {exc}")
65
+ return 1
66
+
67
+
68
+ if __name__ == "__main__":
69
+ raise SystemExit(main())
@@ -0,0 +1,206 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import uuid
5
+ from typing import Any, Dict, List, Optional
6
+
7
+ import requests
8
+
9
+ from .config import (
10
+ DEFAULT_BASE_URL,
11
+ DEFAULT_CLIENT_ID,
12
+ DEFAULT_SESSION_HEADERS,
13
+ DEFAULT_TIMEOUT,
14
+ )
15
+ from .exceptions import ACBAuthenticationError, ACBRequestError
16
+ from .models import AccountBalance, TransactionRecord
17
+
18
+
19
+ def _generate_uuid() -> str:
20
+ return str(uuid.uuid4())
21
+
22
+
23
+ def _generate_device_id() -> str:
24
+ return str(uuid.uuid4()).upper()
25
+
26
+
27
+ class ACBClient:
28
+ """Unofficial ACB API client for balances and transaction history."""
29
+
30
+ def __init__(
31
+ self,
32
+ username: str,
33
+ password: str,
34
+ *,
35
+ base_url: str = DEFAULT_BASE_URL,
36
+ client_id: str = DEFAULT_CLIENT_ID,
37
+ timeout: int = DEFAULT_TIMEOUT,
38
+ debug: bool = False,
39
+ session: Optional[requests.Session] = None,
40
+ ) -> None:
41
+ if not username or not password:
42
+ raise ValueError("Username and password cannot be empty.")
43
+
44
+ self.username = username.strip()
45
+ self.password = password.strip()
46
+ self.base_url = base_url.rstrip("/")
47
+ self.client_id = client_id
48
+ self.timeout = timeout
49
+ self.debug = debug
50
+ self.device_id = _generate_device_id()
51
+ self.access_token: Optional[str] = None
52
+ self.refresh_token: Optional[str] = None
53
+
54
+ self.session = session or requests.Session()
55
+ self.session.headers.update(DEFAULT_SESSION_HEADERS)
56
+
57
+ def _debug(self, message: str) -> None:
58
+ if self.debug:
59
+ print(message)
60
+
61
+ def _get_request_headers(self, include_auth: bool = False) -> Dict[str, str]:
62
+ headers = {"x-request-id": _generate_uuid()}
63
+ if include_auth and self.access_token:
64
+ headers["Authorization"] = f"Bearer {self.access_token}"
65
+ return headers
66
+
67
+ def _request(
68
+ self,
69
+ method: str,
70
+ path: str,
71
+ *,
72
+ headers: Optional[Dict[str, str]] = None,
73
+ data: Optional[str] = None,
74
+ auth_required: bool = False,
75
+ ) -> requests.Response:
76
+ request_headers = self._get_request_headers(include_auth=auth_required)
77
+ if headers:
78
+ request_headers.update(headers)
79
+
80
+ url = f"{self.base_url}{path}"
81
+ self._debug(f"{method.upper()} {url}")
82
+
83
+ try:
84
+ response = self.session.request(
85
+ method=method.upper(),
86
+ url=url,
87
+ headers=request_headers,
88
+ data=data,
89
+ timeout=self.timeout,
90
+ )
91
+ except requests.exceptions.RequestException as exc:
92
+ raise ACBRequestError(f"Request to ACB failed: {exc}") from exc
93
+
94
+ self._debug(f"Status: {response.status_code}")
95
+ if self.debug:
96
+ self._debug(f"Response body: {response.text}")
97
+
98
+ return response
99
+
100
+ def login(self) -> None:
101
+ payload = {
102
+ "username": self.username,
103
+ "password": self.password,
104
+ "deviceId": self.device_id,
105
+ "clientId": self.client_id,
106
+ }
107
+
108
+ response = self._request(
109
+ "POST",
110
+ "/mb/v2/auth/tokens",
111
+ data=json.dumps(payload),
112
+ )
113
+
114
+ if not response.ok:
115
+ raise ACBAuthenticationError(
116
+ f"Authentication failed ({response.status_code}): {response.text}"
117
+ )
118
+
119
+ login_data = response.json()
120
+ self.access_token = login_data.get("accessToken")
121
+ self.refresh_token = login_data.get("refreshToken")
122
+
123
+ if not self.access_token:
124
+ raise ACBAuthenticationError("Authentication succeeded but no access token was returned.")
125
+
126
+ def refresh(self) -> None:
127
+ if not self.refresh_token:
128
+ self.login()
129
+ return
130
+
131
+ response = self._request(
132
+ "POST",
133
+ "/mb/v2/auth/refresh",
134
+ headers={"Authorization": f"Bearer {self.refresh_token}"},
135
+ )
136
+
137
+ if not response.ok:
138
+ self._debug("Refresh failed, retrying with full login.")
139
+ self.login()
140
+ return
141
+
142
+ refresh_data = response.json()
143
+ self.access_token = refresh_data.get("accessToken")
144
+ if not self.access_token:
145
+ self.login()
146
+
147
+ def authenticate(self) -> None:
148
+ if self.refresh_token:
149
+ self.refresh()
150
+ else:
151
+ self.login()
152
+
153
+ def get_balances(self) -> Dict[str, List[AccountBalance]]:
154
+ self.authenticate()
155
+ response = self._request(
156
+ "GET",
157
+ "/mb/legacy/ss/cs/bankservice/transfers/list/account-payment",
158
+ auth_required=True,
159
+ )
160
+
161
+ if not response.ok:
162
+ raise ACBRequestError(
163
+ f"Failed to fetch balances ({response.status_code}): {response.text}"
164
+ )
165
+
166
+ payload = response.json()
167
+ balances: List[AccountBalance] = []
168
+ for account in payload.get("data", []):
169
+ balances.append(
170
+ AccountBalance(
171
+ accountNumber=str(account.get("accountNumber", "")),
172
+ accountDescription=account.get("accountDescription", ""),
173
+ ownerName=account.get("owner", ""),
174
+ currency=account.get("currency", ""),
175
+ balance=float(account.get("balance", 0) or 0),
176
+ totalBalance=float(account.get("totalBalance", 0) or 0),
177
+ status=int(account.get("status", 0) or 0),
178
+ )
179
+ )
180
+ return {"balances": balances}
181
+
182
+ def get_transactions(self, rows: int, account_number: str) -> List[TransactionRecord]:
183
+ self.authenticate()
184
+ path = (
185
+ f"/mb/legacy/ss/cs/bankservice/saving/tx-history?maxRows={rows}"
186
+ f"&account={account_number}"
187
+ )
188
+ response = self._request("GET", path, auth_required=True)
189
+
190
+ if not response.ok:
191
+ raise ACBRequestError(
192
+ f"Failed to fetch transactions ({response.status_code}): {response.text}"
193
+ )
194
+
195
+ payload = response.json()
196
+ data = payload.get("data", [])
197
+ return [TransactionRecord(**item) for item in data]
198
+
199
+ def get_first_account_number(self) -> Optional[str]:
200
+ balances = self.get_balances().get("balances", [])
201
+ if not balances:
202
+ return None
203
+ return balances[0]["accountNumber"]
204
+
205
+
206
+ ACB = ACBClient
@@ -0,0 +1,16 @@
1
+ DEFAULT_BASE_URL = "https://apiapp.acb.com.vn"
2
+ DEFAULT_CLIENT_ID = "iuSuHYVufIUuNIREV0FB9EoLn9kHsDbm"
3
+ DEFAULT_API_KEY = "CQk6S5usauGmMgMYLGqCuDtgtqIM8FI1"
4
+ DEFAULT_APP_VERSION = "3.26.0"
5
+ DEFAULT_USER_AGENT = "ACB-MBA/8 CFNetwork/1335.0.3 Darwin/21.6.0"
6
+ DEFAULT_CONVERSATION_ID = "f43472f1-6d88-4228-91b9-4618a079342a"
7
+ DEFAULT_TIMEOUT = 30
8
+
9
+ DEFAULT_SESSION_HEADERS = {
10
+ "Accept": "application/json, text/plain, */*",
11
+ "Content-Type": "application/json",
12
+ "apikey": DEFAULT_API_KEY,
13
+ "User-Agent": DEFAULT_USER_AGENT,
14
+ "x-app-version": DEFAULT_APP_VERSION,
15
+ "x-conversation-id": DEFAULT_CONVERSATION_ID,
16
+ }
@@ -0,0 +1,10 @@
1
+ class ACBError(Exception):
2
+ """Base exception for the acb_api package."""
3
+
4
+
5
+ class ACBAuthenticationError(ACBError):
6
+ """Raised when authentication with ACB fails."""
7
+
8
+
9
+ class ACBRequestError(ACBError):
10
+ """Raised when an ACB API request fails."""
@@ -0,0 +1,29 @@
1
+ from typing import TypedDict
2
+
3
+
4
+ class AccountBalance(TypedDict):
5
+ accountNumber: str
6
+ accountDescription: str
7
+ ownerName: str
8
+ currency: str
9
+ balance: float
10
+ totalBalance: float
11
+ status: int
12
+
13
+
14
+ class TransactionRecord(TypedDict, total=False):
15
+ amount: float
16
+ accountName: str
17
+ receiverName: str
18
+ transactionNumber: int
19
+ description: str
20
+ bankName: str
21
+ isOnline: bool
22
+ postingDate: int
23
+ accountOwner: str
24
+ type: str
25
+ receiverAccountNumber: str
26
+ currency: str
27
+ account: int
28
+ activeDatetime: int
29
+ effectiveDate: int
@@ -0,0 +1,140 @@
1
+ Metadata-Version: 2.4
2
+ Name: makky-acb-api
3
+ Version: 0.1.0
4
+ Summary: Unofficial Python client for ACB account balances and transaction history
5
+ Author: Makky
6
+ Maintainer: Makky
7
+ Project-URL: Homepage, https://github.com/Makky/ACB-API
8
+ Project-URL: Repository, https://github.com/Makky/ACB-API
9
+ Project-URL: Issues, https://github.com/Makky/ACB-API/issues
10
+ Keywords: acb,banking,api,transactions,payments
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Intended Audience :: Developers
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ Requires-Dist: requests>=2.31.0
23
+ Requires-Dist: python-dotenv>=1.0.0
24
+
25
+ # makky-acb-api
26
+
27
+ **πŸ‡ΊπŸ‡Έ English** | [πŸ‡»πŸ‡³ TiαΊΏng Việt](README_VI.md)
28
+
29
+ Unofficial Python client for ACB account balances and transaction history, packaged for local installation and future PyPI publication.
30
+
31
+ ## Features
32
+
33
+ - Authenticate with ACB using username and password
34
+ - Fetch balances for payment accounts
35
+ - Retrieve recent transaction history for a selected account
36
+ - Use as a Python library or from a CLI command
37
+
38
+ ## Installation
39
+
40
+ ### Local development install
41
+
42
+ ```bash
43
+ pip install -r requirements.txt
44
+ pip install -e .
45
+ ```
46
+
47
+ ### After publication to PyPI
48
+
49
+ ```bash
50
+ pip install makky-acb-api
51
+ ```
52
+
53
+ ## Environment variables
54
+
55
+ Create a `.env` file in the project root:
56
+
57
+ ```env
58
+ ACB_USERNAME=your_username
59
+ ACB_PASSWORD=your_password
60
+ ```
61
+
62
+ > [!WARNING]
63
+ > This project uses an unofficial ACB API. Protect your credentials and use it at your own risk.
64
+
65
+ ## Python usage
66
+
67
+ ```python
68
+ from acb_api import ACBClient
69
+
70
+ client = ACBClient(username="your_username", password="your_password")
71
+ balances = client.get_balances()
72
+ print(balances)
73
+
74
+ account = balances["balances"][0]["accountNumber"]
75
+ transactions = client.get_transactions(rows=5, account_number=account)
76
+ print(transactions)
77
+ ```
78
+
79
+ ## CLI usage
80
+
81
+ After `pip install -e .`, run:
82
+
83
+ ```bash
84
+ acb-api --action all --rows 5
85
+ ```
86
+
87
+ Other examples:
88
+
89
+ ```bash
90
+ acb-api --action balances
91
+ acb-api --action transactions --account 19527581 --rows 10
92
+ acb-api --action all --debug
93
+ ```
94
+
95
+ ## Local demo script
96
+
97
+ For backward-compatible local testing:
98
+
99
+ ```bash
100
+ python main.py
101
+ ```
102
+
103
+ ## Project structure
104
+
105
+ ```text
106
+ ACB-API/
107
+ β”œβ”€β”€ src/acb_api/
108
+ β”‚ β”œβ”€β”€ __init__.py
109
+ β”‚ β”œβ”€β”€ cli.py
110
+ β”‚ β”œβ”€β”€ client.py
111
+ β”‚ β”œβ”€β”€ config.py
112
+ β”‚ β”œβ”€β”€ exceptions.py
113
+ β”‚ └── models.py
114
+ β”œβ”€β”€ main.py
115
+ β”œβ”€β”€ pyproject.toml
116
+ └── README.md
117
+ ```
118
+
119
+ ## Packaging notes
120
+
121
+ - Distribution/package name: `makky-acb-api`
122
+ - Import package name: `acb_api`
123
+ - Author / maintainer: `Makky`
124
+
125
+ To build distributable artifacts locally:
126
+
127
+ ```bash
128
+ python -m build
129
+ ```
130
+
131
+ ## Credits
132
+
133
+ This packaged version is maintained by **Makky**.
134
+
135
+ Inspired by earlier community work around ACB unofficial integrations, including:
136
+ - [anhnmt/ACB](https://github.com/anhnmt/ACB)
137
+
138
+ ## Disclaimer
139
+
140
+ This is an unofficial client and is not affiliated with ACB. APIs, headers, and authentication flows may change without notice. Use at your own risk.
@@ -0,0 +1,15 @@
1
+ MANIFEST.in
2
+ README.md
3
+ pyproject.toml
4
+ src/acb_api/__init__.py
5
+ src/acb_api/cli.py
6
+ src/acb_api/client.py
7
+ src/acb_api/config.py
8
+ src/acb_api/exceptions.py
9
+ src/acb_api/models.py
10
+ src/makky_acb_api.egg-info/PKG-INFO
11
+ src/makky_acb_api.egg-info/SOURCES.txt
12
+ src/makky_acb_api.egg-info/dependency_links.txt
13
+ src/makky_acb_api.egg-info/entry_points.txt
14
+ src/makky_acb_api.egg-info/requires.txt
15
+ src/makky_acb_api.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ acb-api = acb_api.cli:main
@@ -0,0 +1,2 @@
1
+ requests>=2.31.0
2
+ python-dotenv>=1.0.0