sub2api_utils
A user-side Python programming interface for Sub2API (the open-source project Wei-Shaw/sub2api). Pure standard library, zero third-party dependencies (Python 3.10+).
No CLI, no GUI — just an importable object-oriented interface.
Project layout
sub2api_utils/
├── sub2api_utils/
│ ├── __init__.py # public interface exports
│ └── main.py # implementation (standard library only)
├── pyproject.toml # packaging metadata
└── README.md
Quick start
from datetime import datetime
from sub2api_utils import Sub2ApiLoginSession, DayPeriod, SimpleStat
BASE_URL = "https://your-sub-to-api-website"
# 1) Log in (the password is validated immediately; raises Sub2APIError if wrong)
session = Sub2ApiLoginSession(BASE_URL, "you@example.com", "your-password")
# 2) List all API keys of this user
keys = session.get_api_key_list()
for k in keys:
print(k.get_str_form()) # sk-xxx
print(k.get_user_email()) # the email the key belongs to
print(k.get_key_name()) # the key's name on the site, e.g. 'Main Key'
# 3) Actual usage (in $) of a key over an arbitrary time range, precise to the hour
key = keys[0]
usd = key.get_stat("your-password",
datetime(2026, 9, 25, 14, 0), # start (inclusive)
datetime(2026, 9, 28, 9, 0)) # end (exclusive), [start, end)
print(usd)
# 4) Per-day usage for every day in a date period (reuses the same login session)
daily = key.get_stat_in_period("your-password", DayPeriod(2026, 9, 25, 3))
print(daily) # [day1, day2, day3]
# 5) A manually constructed key works too (it logs in lazily on first use)
from sub2api_utils import Sub2ApiKey
manual = Sub2ApiKey(BASE_URL, "you@example.com", "sk-xxx")
print(manual.get_stat("your-password", datetime(2026, 9, 25), datetime(2026, 9, 26)))
# 6) Managing multiple users + a usage matrix
from sub2api_utils import Sub2ApiUserInfoSet
us = Sub2ApiUserInfoSet(base_url=BASE_URL) # base_url is required
us.add_user_info("a@example.com", "pwd-a") # password is validated on add
us.add_user_info("b@example.com", "pwd-b")
matrix = us.get_stat_matrix(DayPeriod(2026, 9, 25, 2))
# matrix = { "a@example.com": {"sk-1": [d1, d2], ...}, ... }
us.del_user_info("a@example.com")
# 7) Simple statistics
stat = SimpleStat(matrix["b@example.com"]["sk-2"])
print(stat.average(), stat.variation(), stat.stdvar())
Classes and methods
| Class | Method | Description |
|---|---|---|
Sub2ApiLoginSession |
__init__(base_url, user_email, password, *, timeout=30, verify_ssl=True, timezone="Asia/Shanghai") |
Logs in and validates the password; raises Sub2APIError on failure |
get_api_key_list() -> list[Sub2ApiKey] |
All API keys of the current user | |
get_api_key_stat(key, begin_time, end_time) -> float |
Actual usage ($) of the key over [begin, end) |
|
Sub2ApiKey |
get_str_form() / get_user_email() / get_base_url() |
Basic info |
get_key_name() -> str | None |
The key's string name on the site (e.g. Main Key) |
|
get_stat(password, begin_time, end_time) -> float |
Usage (logs in lazily on first call, then reuses the session) | |
get_stat_in_period(password, days) -> list[float] |
Per-day usage over the date period | |
DayPeriod |
DayPeriod(year, month, day, duration) + four getters |
Start date + duration in days (positive integer) |
Sub2ApiUserInfoSet |
__init__(*, base_url=...) / add_user_info(email, password) / del_user_info(email) |
Add (validates password) / remove users |
get_api_key_list() -> list[Sub2ApiKey] |
All keys of all users | |
get_stat_matrix(days) -> dict[email, dict[key_str, list[float]]] |
Per-user, per-key, per-day usage matrix | |
SimpleStat |
foldl / average / variation / stdvar |
Left fold / mean / variance / standard deviation |
Sub2APIError |
— | Interface error (carries HTTP status, backend code/reason) |
Implementation notes (verified against the Wei-Shaw/sub2api source)
The client calls the Sub2API user-side HTTP API:
| Purpose | Endpoint |
|---|---|
| Login (username = email) | POST /api/v1/auth/login → data.access_token |
| Key listing (paginated) | GET /api/v1/keys, Authorization: Bearer <token> |
| Hourly / daily usage | GET /api/v1/usage/dashboard/trend?granularity=hour|day |
| Usage records (fallback) | GET /api/v1/usage (paginated) |
- Base URL: no site address is hardcoded in the library. Pass
base_urlexplicitly toSub2ApiLoginSession/Sub2ApiKey/Sub2ApiUserInfoSet. - Hour precision:
get_statsums the hourly trend buckets over the exact[begin, end)range, so the boundaries can be precise to the hour (the backend only accepts day-precision range inputs; extra buckets are dropped client-side). - Key name:
get_key_name()reads thenamefield of/api/v1/keys. Keys fromget_api_key_list()carry the name; a manually constructed key is looked up (and cached) once a login session exists;Noneis returned when neither is available. - Cost basis: the value returned is
actual_cost(the amount actually charged, i.e. the real $), not the token count. - Fallback: if the backend has no
dashboard/trendendpoint, the client automatically aggregates the per-record usage from/api/v1/usageinstead; results are equivalent. - Timezone:
timezonedecides where the boundaries of a "day"/"hour" fall (defaultAsia/Shanghai). When the system lacks tzdata, a built-in fixed-offset table is used, so notzdatapackage is required. - Session reuse:
Sub2ApiKey.get_stat/get_stat_in_periodlog in on the first call and cache the session for later calls; the session is rebuilt when the password changes. If anaccess_tokenexpires (HTTP 401), the client re-logs in with the stored password and retries once. - 2FA: if the account has TOTP two-factor authentication enabled, the login
response has no
access_tokenandSub2APIErrorreports it clearly (that flow requires/login/2fa; this library does not automate it). - Note: in the class skeleton,
get_stat_in_periodwas originally annotated as returninglist[str]; it is implemented aslist[float](per-day dollar amounts, consistent with the innerlist[float]ofget_stat_matrix).
Metadata
Release files for sub2api-utils 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sub2api_utils-0.1.0.tar.gz | 12.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sub2api_utils-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 25.1 kB
Release files / sub2api_utils-0.1.0.tar.gz
| Download URL | sub2api_utils-0.1.0.tar.gz |
|---|---|
| Size | 12.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
afcb689a2472b5620e608dd46ca7cf82c65f5f5f49659a7833dff447d95c7e80
|
|
BLAKE2b-256 checksum How to use checksums |
46d59e6bd4efe03ac2687bb78a942e9774fea8958f3262c5609869ddcda6d8ce
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.1 CPython/3.14.6 Windows/11
|
Release files / sub2api_utils-0.1.0-py3-none-any.whl
| Download URL | sub2api_utils-0.1.0-py3-none-any.whl |
|---|---|
| Size | 12.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0d99c4822933921d62700d4ec6b621e0dbb08373a29e42120eb0d98331ff5611
|
|
BLAKE2b-256 checksum How to use checksums |
db7dd83cb7c3b8591a061514295745988fb0f4ae2e041ecbbfc02264e3a75006
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.1 CPython/3.14.6 Windows/11
|