Skip to main content

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_url explicitly to Sub2ApiLoginSession / Sub2ApiKey / Sub2ApiUserInfoSet.
  • Hour precision: get_stat sums 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 the name field of /api/v1/keys. Keys from get_api_key_list() carry the name; a manually constructed key is looked up (and cached) once a login session exists; None is 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/trend endpoint, the client automatically aggregates the per-record usage from /api/v1/usage instead; results are equivalent.
  • Timezone: timezone decides where the boundaries of a "day"/"hour" fall (default Asia/Shanghai). When the system lacks tzdata, a built-in fixed-offset table is used, so no tzdata package is required.
  • Session reuse: Sub2ApiKey.get_stat / get_stat_in_period log in on the first call and cache the session for later calls; the session is rebuilt when the password changes. If an access_token expires (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_token and Sub2APIError reports it clearly (that flow requires /login/2fa; this library does not automate it).
  • Note: in the class skeleton, get_stat_in_period was originally annotated as returning list[str]; it is implemented as list[float] (per-day dollar amounts, consistent with the inner list[float] of get_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)

Source distribution for sub2api-utils 0.1.0
File Size Uploaded
sub2api_utils-0.1.0.tar.gz 12.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sub2api-utils 0.1.0
File Interpreter ABI Platform
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

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page