newapi-python 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,11 @@
1
+ *.har
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .coverage
5
+ .mypy_cache/
6
+ .pytest_cache/
7
+ .ruff_cache/
8
+ .venv/
9
+ build/
10
+ dist/
11
+ __pycache__/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eight Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,267 @@
1
+ Metadata-Version: 2.5
2
+ Name: newapi-python
3
+ Version: 0.1.0
4
+ Summary: Python client for the user-facing dashboard API of new-api instances
5
+ Author: Eight Labs
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Keywords: ai-gateway,api,new-api,one-api,sdk
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Typing :: Typed
18
+ Requires-Python: >=3.10
19
+ Requires-Dist: curl-cffi<1,>=0.10
20
+ Provides-Extra: dev
21
+ Requires-Dist: build>=1.2; extra == 'dev'
22
+ Requires-Dist: cryptography>=43; extra == 'dev'
23
+ Requires-Dist: httpx<1,>=0.27; extra == 'dev'
24
+ Requires-Dist: mypy>=1.11; extra == 'dev'
25
+ Requires-Dist: pytest-cov>=5; extra == 'dev'
26
+ Requires-Dist: pytest>=8; extra == 'dev'
27
+ Requires-Dist: ruff>=0.7; extra == 'dev'
28
+ Requires-Dist: twine>=5; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # new-api
32
+
33
+ `newapi` is a Python client for the shared user-facing dashboard API exposed by [new-api](https://github.com/QuantumNous/new-api) instances. One client object represents one user's in-memory dashboard session. Requests use `curl_cffi` with Chrome browser impersonation by default.
34
+
35
+ The library targets operations present on standard new-api deployments: account profile, quota balance, gateway tokens, usage logs and statistics, dashboard data, usable groups, optional top-up and online payment, redemption codes, subscriptions, check-in, and login-session management.
36
+
37
+ ## Install
38
+
39
+ ```bash
40
+ pip install newapi-python
41
+ ```
42
+
43
+ Python 3.10 or newer is required.
44
+
45
+ ## Authenticate with an existing session
46
+
47
+ The dashboard's access token is different from an `sk-...` gateway token. Browser deployments normally hold the session access token in memory after login or refresh, and keep the rotating refresh credential in the HttpOnly `new_api_refresh` cookie scoped to `/api/user/auth`.
48
+
49
+ ```python
50
+ import os
51
+
52
+ from newapi import NewAPI
53
+
54
+ client = NewAPI(
55
+ "https://newapi.example.com",
56
+ access_token=os.environ["NEWAPI_ACCESS_TOKEN"],
57
+ refresh_token=os.environ.get("NEWAPI_REFRESH_TOKEN"),
58
+ )
59
+ ```
60
+
61
+ Pass either the instance origin or its full `/api` URL. Tokens are retained only in memory. If a refresh token is supplied, the client sends it as the `new_api_refresh` cookie, rotates the pair after an authenticated `401`, and refreshes proactively when `expires_at` is known. Users can also generate a long-lived system access token from the dashboard and pass it as `access_token` alone; such tokens cannot refresh browser sessions.
62
+
63
+ The default browser fingerprint is Chrome. Choose another `curl_cffi` fingerprint or configure proxies by supplying your own `curl_cffi.requests.Session`:
64
+
65
+ ```python
66
+ from curl_cffi import requests
67
+
68
+ session = requests.Session(impersonate="safari")
69
+ client = NewAPI("https://newapi.example.com", session=session)
70
+ ```
71
+
72
+ ## Log in with username and password
73
+
74
+ ```python
75
+ from newapi import NewAPI
76
+
77
+ with NewAPI("https://newapi.example.com") as client:
78
+ user = client.login("root", "password")
79
+ print(user.username, user.quota)
80
+ print(client.is_authenticated)
81
+ ```
82
+
83
+ When the instance enables login password encryption, the client fetches the RSA public key from `/api/user/login/encryption-key` and submits an RSA-OAEP/SHA-256 ciphertext, matching the browser. Pass `encrypt_password=False` to send the plaintext password instead. An instance with Cloudflare Turnstile enabled requires the corresponding proof:
84
+
85
+ ```python
86
+ client.login("root", "password", turnstile_token="captcha-proof")
87
+ ```
88
+
89
+ For a TOTP-enabled account, `login()` raises `TwoFactorRequired` and retains the flow token in memory:
90
+
91
+ ```python
92
+ from newapi import NewAPI, TwoFactorRequired
93
+
94
+ client = NewAPI("https://newapi.example.com")
95
+
96
+ try:
97
+ client.login("root", "password")
98
+ except TwoFactorRequired:
99
+ client.complete_2fa("123456")
100
+ ```
101
+
102
+ ## Common operations
103
+
104
+ Resources are callable for their common list operation and also expose explicit methods.
105
+
106
+ ```python
107
+ balance = client.balance()
108
+ print(balance.quota, balance.amount)
109
+
110
+ status = client.status()
111
+ groups = client.groups()
112
+ print(groups["vip"].ratio, groups["vip"].desc)
113
+
114
+ models = client.account.models()
115
+ print(client.account.aff_code())
116
+ ```
117
+
118
+ `balance()` reports raw quota integers plus `amount`, `used_amount`, and `aff_amount` as `Decimal` values converted with the instance's `quota_per_unit` (default `500000`).
119
+
120
+ ## Gateway tokens
121
+
122
+ `tokens` and `keys` refer to the same resource. Instances return masked key values in list responses; call `reveal()` to fetch the full `sk-...` value.
123
+
124
+ ```python
125
+ first_page = client.tokens(page_size=50)
126
+ for token in first_page:
127
+ print(token.id, token.name, token.status, token.remain_quota)
128
+
129
+ all_tokens = client.tokens.all()
130
+
131
+ client.tokens.create("automation", group="default")
132
+ token, key = client.tokens.create_and_reveal("automation", group="default")
133
+ client.tokens.update(token.id, name="nightly automation")
134
+ client.tokens.disable(token.id)
135
+ client.tokens.enable(token.id)
136
+ client.tokens.delete(token.id)
137
+
138
+ print(client.tokens.reveal(token.id))
139
+ print(client.tokens.reveal_batch([1, 2, 3]))
140
+ print(client.tokens.auto_groups())
141
+ ```
142
+
143
+ Token creation does not echo the new record from the instance, so `create()` returns `None`; `create_and_reveal()` creates the token, finds it in the list, and returns the record together with its full key. `update()` reads the current token first and resubmits preserved values for any field you leave out, because the instance replaces the whole record on update. `expired_time` accepts a Unix timestamp, a `datetime`, or `-1` for no expiry. `allow_ips` accepts a comma-separated string or a sequence of strings.
144
+
145
+ ## Usage history
146
+
147
+ `history`, `usage`, and `logs` refer to the same resource.
148
+
149
+ ```python
150
+ from datetime import datetime, timedelta, timezone
151
+
152
+ end = datetime.now(timezone.utc)
153
+ start = end - timedelta(days=7)
154
+
155
+ page = client.history(
156
+ log_type="consume",
157
+ start_timestamp=start,
158
+ end_timestamp=end,
159
+ page_size=100,
160
+ )
161
+
162
+ for record in page:
163
+ print(record.created_at, record.model_name, record.quota, record.prompt_tokens)
164
+
165
+ for record in client.history.iter(log_type="consume", page_size=100):
166
+ process(record)
167
+
168
+ stats = client.logs.stat(log_type="consume", start_timestamp=start, end_timestamp=end)
169
+ print(stats.quota, stats.rpm, stats.tpm)
170
+ ```
171
+
172
+ `log_type` accepts an integer or one of `topup`, `consume`, `manage`, `system`, `error`, `refund`, and `login`. Timestamps accept `datetime` objects or Unix seconds.
173
+
174
+ ## Dashboard data
175
+
176
+ ```python
177
+ rows = client.dashboard.quota_data(start_timestamp=start, end_timestamp=end)
178
+ flow = client.dashboard.flow_data(start_timestamp=start, end_timestamp=end)
179
+ ```
180
+
181
+ Both endpoints limit the time span to one month; `flow_data` requires explicit positive bounds.
182
+
183
+ ## Top-up, redemption, and payment
184
+
185
+ Online payment is optional and must be enabled and configured by the instance administrator. Inspect the top-up configuration before offering a recharge:
186
+
187
+ ```python
188
+ info = client.topup.info()
189
+
190
+ if info.enable_stripe_topup:
191
+ link = client.payment.stripe_pay(10)
192
+ print(link)
193
+
194
+ if info.enable_online_topup:
195
+ amount = client.payment.epay_amount(10)
196
+ checkout = client.payment.epay_pay(10, "alipay")
197
+ print(checkout.url, checkout.params)
198
+ ```
199
+
200
+ Creating an order does not credit the balance; the configured provider must confirm payment before the instance completes the top-up. Track the resulting orders and redeem codes with:
201
+
202
+ ```python
203
+ orders = client.topup.orders()
204
+ result = client.topup.redeem("REDEMPTION-CODE")
205
+ print(result.quota)
206
+ ```
207
+
208
+ ## Subscriptions
209
+
210
+ ```python
211
+ plans = client.subscriptions.plans()
212
+ overview = client.subscriptions.self()
213
+ client.subscriptions.set_preference("balance_first")
214
+ client.subscriptions.purchase_with_balance(plans[0].id)
215
+ ```
216
+
217
+ ## Check-in
218
+
219
+ ```python
220
+ status = client.account.checkin_status()
221
+ if status.enabled:
222
+ result = client.account.checkin()
223
+ print(result.quota_awarded, result.checkin_date)
224
+ ```
225
+
226
+ ## Login sessions
227
+
228
+ ```python
229
+ for entry in client.account.sessions():
230
+ print(entry.sid, entry.login_method, entry.current)
231
+
232
+ client.account.revoke_session("sid-from-another-device")
233
+ client.account.revoke_other_sessions()
234
+ ```
235
+
236
+ These endpoints require a browser login session; long-lived system access tokens are rejected.
237
+
238
+ ## Fork-specific endpoints
239
+
240
+ `request()` provides the same authentication, envelope handling, refresh behavior, and error mapping for relative endpoints that are not part of the stable resource API.
241
+
242
+ ```python
243
+ result = client.request("GET", "user/self")
244
+ ```
245
+
246
+ Absolute URLs and parent-path traversal are rejected so a session token cannot be redirected outside the configured API root.
247
+
248
+ ## Errors
249
+
250
+ HTTP failures and new-api envelope failures use typed exceptions:
251
+
252
+ ```python
253
+ from newapi import APIError, AuthenticationError, NewAPIError, RateLimitError
254
+
255
+ try:
256
+ client.tokens.create("automation")
257
+ except RateLimitError as error:
258
+ print(error.retry_after)
259
+ except AuthenticationError:
260
+ client.login("root", "password")
261
+ except NewAPIError as error:
262
+ print(error)
263
+ ```
264
+
265
+ Most new-api business errors arrive as HTTP `200` with `success: false`; they raise `APIError` with the instance's message. Middleware failures use real HTTP statuses and map to `AuthenticationError`, `PermissionDeniedError`, `RateLimitError`, and friends. Object representations redact fields that commonly contain credentials.
266
+
267
+ Remote plaintext HTTP is rejected by default because it exposes login credentials and tokens. Localhost HTTP is allowed for development; other HTTP instances require `allow_insecure=True`.
@@ -0,0 +1,237 @@
1
+ # new-api
2
+
3
+ `newapi` is a Python client for the shared user-facing dashboard API exposed by [new-api](https://github.com/QuantumNous/new-api) instances. One client object represents one user's in-memory dashboard session. Requests use `curl_cffi` with Chrome browser impersonation by default.
4
+
5
+ The library targets operations present on standard new-api deployments: account profile, quota balance, gateway tokens, usage logs and statistics, dashboard data, usable groups, optional top-up and online payment, redemption codes, subscriptions, check-in, and login-session management.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pip install newapi-python
11
+ ```
12
+
13
+ Python 3.10 or newer is required.
14
+
15
+ ## Authenticate with an existing session
16
+
17
+ The dashboard's access token is different from an `sk-...` gateway token. Browser deployments normally hold the session access token in memory after login or refresh, and keep the rotating refresh credential in the HttpOnly `new_api_refresh` cookie scoped to `/api/user/auth`.
18
+
19
+ ```python
20
+ import os
21
+
22
+ from newapi import NewAPI
23
+
24
+ client = NewAPI(
25
+ "https://newapi.example.com",
26
+ access_token=os.environ["NEWAPI_ACCESS_TOKEN"],
27
+ refresh_token=os.environ.get("NEWAPI_REFRESH_TOKEN"),
28
+ )
29
+ ```
30
+
31
+ Pass either the instance origin or its full `/api` URL. Tokens are retained only in memory. If a refresh token is supplied, the client sends it as the `new_api_refresh` cookie, rotates the pair after an authenticated `401`, and refreshes proactively when `expires_at` is known. Users can also generate a long-lived system access token from the dashboard and pass it as `access_token` alone; such tokens cannot refresh browser sessions.
32
+
33
+ The default browser fingerprint is Chrome. Choose another `curl_cffi` fingerprint or configure proxies by supplying your own `curl_cffi.requests.Session`:
34
+
35
+ ```python
36
+ from curl_cffi import requests
37
+
38
+ session = requests.Session(impersonate="safari")
39
+ client = NewAPI("https://newapi.example.com", session=session)
40
+ ```
41
+
42
+ ## Log in with username and password
43
+
44
+ ```python
45
+ from newapi import NewAPI
46
+
47
+ with NewAPI("https://newapi.example.com") as client:
48
+ user = client.login("root", "password")
49
+ print(user.username, user.quota)
50
+ print(client.is_authenticated)
51
+ ```
52
+
53
+ When the instance enables login password encryption, the client fetches the RSA public key from `/api/user/login/encryption-key` and submits an RSA-OAEP/SHA-256 ciphertext, matching the browser. Pass `encrypt_password=False` to send the plaintext password instead. An instance with Cloudflare Turnstile enabled requires the corresponding proof:
54
+
55
+ ```python
56
+ client.login("root", "password", turnstile_token="captcha-proof")
57
+ ```
58
+
59
+ For a TOTP-enabled account, `login()` raises `TwoFactorRequired` and retains the flow token in memory:
60
+
61
+ ```python
62
+ from newapi import NewAPI, TwoFactorRequired
63
+
64
+ client = NewAPI("https://newapi.example.com")
65
+
66
+ try:
67
+ client.login("root", "password")
68
+ except TwoFactorRequired:
69
+ client.complete_2fa("123456")
70
+ ```
71
+
72
+ ## Common operations
73
+
74
+ Resources are callable for their common list operation and also expose explicit methods.
75
+
76
+ ```python
77
+ balance = client.balance()
78
+ print(balance.quota, balance.amount)
79
+
80
+ status = client.status()
81
+ groups = client.groups()
82
+ print(groups["vip"].ratio, groups["vip"].desc)
83
+
84
+ models = client.account.models()
85
+ print(client.account.aff_code())
86
+ ```
87
+
88
+ `balance()` reports raw quota integers plus `amount`, `used_amount`, and `aff_amount` as `Decimal` values converted with the instance's `quota_per_unit` (default `500000`).
89
+
90
+ ## Gateway tokens
91
+
92
+ `tokens` and `keys` refer to the same resource. Instances return masked key values in list responses; call `reveal()` to fetch the full `sk-...` value.
93
+
94
+ ```python
95
+ first_page = client.tokens(page_size=50)
96
+ for token in first_page:
97
+ print(token.id, token.name, token.status, token.remain_quota)
98
+
99
+ all_tokens = client.tokens.all()
100
+
101
+ client.tokens.create("automation", group="default")
102
+ token, key = client.tokens.create_and_reveal("automation", group="default")
103
+ client.tokens.update(token.id, name="nightly automation")
104
+ client.tokens.disable(token.id)
105
+ client.tokens.enable(token.id)
106
+ client.tokens.delete(token.id)
107
+
108
+ print(client.tokens.reveal(token.id))
109
+ print(client.tokens.reveal_batch([1, 2, 3]))
110
+ print(client.tokens.auto_groups())
111
+ ```
112
+
113
+ Token creation does not echo the new record from the instance, so `create()` returns `None`; `create_and_reveal()` creates the token, finds it in the list, and returns the record together with its full key. `update()` reads the current token first and resubmits preserved values for any field you leave out, because the instance replaces the whole record on update. `expired_time` accepts a Unix timestamp, a `datetime`, or `-1` for no expiry. `allow_ips` accepts a comma-separated string or a sequence of strings.
114
+
115
+ ## Usage history
116
+
117
+ `history`, `usage`, and `logs` refer to the same resource.
118
+
119
+ ```python
120
+ from datetime import datetime, timedelta, timezone
121
+
122
+ end = datetime.now(timezone.utc)
123
+ start = end - timedelta(days=7)
124
+
125
+ page = client.history(
126
+ log_type="consume",
127
+ start_timestamp=start,
128
+ end_timestamp=end,
129
+ page_size=100,
130
+ )
131
+
132
+ for record in page:
133
+ print(record.created_at, record.model_name, record.quota, record.prompt_tokens)
134
+
135
+ for record in client.history.iter(log_type="consume", page_size=100):
136
+ process(record)
137
+
138
+ stats = client.logs.stat(log_type="consume", start_timestamp=start, end_timestamp=end)
139
+ print(stats.quota, stats.rpm, stats.tpm)
140
+ ```
141
+
142
+ `log_type` accepts an integer or one of `topup`, `consume`, `manage`, `system`, `error`, `refund`, and `login`. Timestamps accept `datetime` objects or Unix seconds.
143
+
144
+ ## Dashboard data
145
+
146
+ ```python
147
+ rows = client.dashboard.quota_data(start_timestamp=start, end_timestamp=end)
148
+ flow = client.dashboard.flow_data(start_timestamp=start, end_timestamp=end)
149
+ ```
150
+
151
+ Both endpoints limit the time span to one month; `flow_data` requires explicit positive bounds.
152
+
153
+ ## Top-up, redemption, and payment
154
+
155
+ Online payment is optional and must be enabled and configured by the instance administrator. Inspect the top-up configuration before offering a recharge:
156
+
157
+ ```python
158
+ info = client.topup.info()
159
+
160
+ if info.enable_stripe_topup:
161
+ link = client.payment.stripe_pay(10)
162
+ print(link)
163
+
164
+ if info.enable_online_topup:
165
+ amount = client.payment.epay_amount(10)
166
+ checkout = client.payment.epay_pay(10, "alipay")
167
+ print(checkout.url, checkout.params)
168
+ ```
169
+
170
+ Creating an order does not credit the balance; the configured provider must confirm payment before the instance completes the top-up. Track the resulting orders and redeem codes with:
171
+
172
+ ```python
173
+ orders = client.topup.orders()
174
+ result = client.topup.redeem("REDEMPTION-CODE")
175
+ print(result.quota)
176
+ ```
177
+
178
+ ## Subscriptions
179
+
180
+ ```python
181
+ plans = client.subscriptions.plans()
182
+ overview = client.subscriptions.self()
183
+ client.subscriptions.set_preference("balance_first")
184
+ client.subscriptions.purchase_with_balance(plans[0].id)
185
+ ```
186
+
187
+ ## Check-in
188
+
189
+ ```python
190
+ status = client.account.checkin_status()
191
+ if status.enabled:
192
+ result = client.account.checkin()
193
+ print(result.quota_awarded, result.checkin_date)
194
+ ```
195
+
196
+ ## Login sessions
197
+
198
+ ```python
199
+ for entry in client.account.sessions():
200
+ print(entry.sid, entry.login_method, entry.current)
201
+
202
+ client.account.revoke_session("sid-from-another-device")
203
+ client.account.revoke_other_sessions()
204
+ ```
205
+
206
+ These endpoints require a browser login session; long-lived system access tokens are rejected.
207
+
208
+ ## Fork-specific endpoints
209
+
210
+ `request()` provides the same authentication, envelope handling, refresh behavior, and error mapping for relative endpoints that are not part of the stable resource API.
211
+
212
+ ```python
213
+ result = client.request("GET", "user/self")
214
+ ```
215
+
216
+ Absolute URLs and parent-path traversal are rejected so a session token cannot be redirected outside the configured API root.
217
+
218
+ ## Errors
219
+
220
+ HTTP failures and new-api envelope failures use typed exceptions:
221
+
222
+ ```python
223
+ from newapi import APIError, AuthenticationError, NewAPIError, RateLimitError
224
+
225
+ try:
226
+ client.tokens.create("automation")
227
+ except RateLimitError as error:
228
+ print(error.retry_after)
229
+ except AuthenticationError:
230
+ client.login("root", "password")
231
+ except NewAPIError as error:
232
+ print(error)
233
+ ```
234
+
235
+ Most new-api business errors arrive as HTTP `200` with `success: false`; they raise `APIError` with the instance's message. Middleware failures use real HTTP statuses and map to `AuthenticationError`, `PermissionDeniedError`, `RateLimitError`, and friends. Object representations redact fields that commonly contain credentials.
236
+
237
+ Remote plaintext HTTP is rejected by default because it exposes login credentials and tokens. Localhost HTTP is allowed for development; other HTTP instances require `allow_insecure=True`.
@@ -0,0 +1,62 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.26"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "newapi-python"
7
+ version = "0.1.0"
8
+ description = "Python client for the user-facing dashboard API of new-api instances"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [
14
+ { name = "Eight Labs" }
15
+ ]
16
+ keywords = ["new-api", "one-api", "api", "sdk", "ai-gateway"]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Intended Audience :: Developers",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Typing :: Typed"
27
+ ]
28
+ dependencies = [
29
+ "curl-cffi>=0.10,<1"
30
+ ]
31
+
32
+ [project.optional-dependencies]
33
+ dev = [
34
+ "build>=1.2",
35
+ "cryptography>=43",
36
+ "httpx>=0.27,<1",
37
+ "mypy>=1.11",
38
+ "pytest>=8",
39
+ "pytest-cov>=5",
40
+ "ruff>=0.7",
41
+ "twine>=5"
42
+ ]
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["src/newapi"]
46
+
47
+ [tool.pytest.ini_options]
48
+ addopts = "-ra"
49
+ testpaths = ["tests"]
50
+
51
+ [tool.ruff]
52
+ line-length = 100
53
+ target-version = "py310"
54
+
55
+ [tool.ruff.lint]
56
+ select = ["E", "F", "I", "UP", "B", "SIM", "RUF"]
57
+
58
+ [tool.mypy]
59
+ python_version = "3.10"
60
+ strict = true
61
+ packages = ["newapi"]
62
+ mypy_path = "src"
@@ -0,0 +1,75 @@
1
+ from ._client import NewAPI
2
+ from ._exceptions import (
3
+ APIError,
4
+ AuthenticationError,
5
+ ConfigurationError,
6
+ ConflictError,
7
+ NewAPIError,
8
+ NotFoundError,
9
+ PermissionDeniedError,
10
+ ProtocolError,
11
+ RateLimitError,
12
+ TransportError,
13
+ TwoFactorRequired,
14
+ ValidationError,
15
+ )
16
+ from ._models import (
17
+ Announcement,
18
+ APIKey,
19
+ Balance,
20
+ CheckinResult,
21
+ CheckinStatus,
22
+ Group,
23
+ Log,
24
+ LoginSession,
25
+ Page,
26
+ PaymentConfig,
27
+ PaymentLink,
28
+ Redemption,
29
+ Resource,
30
+ SessionTokens,
31
+ Subscription,
32
+ SubscriptionPlan,
33
+ Token,
34
+ TopUpOrder,
35
+ UsageRecord,
36
+ User,
37
+ )
38
+
39
+ __all__ = [
40
+ "APIError",
41
+ "APIKey",
42
+ "Announcement",
43
+ "AuthenticationError",
44
+ "Balance",
45
+ "CheckinResult",
46
+ "CheckinStatus",
47
+ "ConfigurationError",
48
+ "ConflictError",
49
+ "Group",
50
+ "Log",
51
+ "LoginSession",
52
+ "NewAPI",
53
+ "NewAPIError",
54
+ "NotFoundError",
55
+ "Page",
56
+ "PaymentConfig",
57
+ "PaymentLink",
58
+ "PermissionDeniedError",
59
+ "ProtocolError",
60
+ "RateLimitError",
61
+ "Redemption",
62
+ "Resource",
63
+ "SessionTokens",
64
+ "Subscription",
65
+ "SubscriptionPlan",
66
+ "Token",
67
+ "TopUpOrder",
68
+ "TransportError",
69
+ "TwoFactorRequired",
70
+ "UsageRecord",
71
+ "User",
72
+ "ValidationError",
73
+ ]
74
+
75
+ __version__ = "0.1.0"