new-api
newapi is a Python client for the shared user-facing dashboard API exposed by new-api instances. One client object represents one user's in-memory dashboard session. Requests use curl_cffi with Chrome browser impersonation by default.
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.
Install
pip install newapi-python
Python 3.10 or newer is required.
Authenticate with an existing session
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.
import os
from newapi import NewAPI
client = NewAPI(
"https://newapi.example.com",
access_token=os.environ["NEWAPI_ACCESS_TOKEN"],
refresh_token=os.environ.get("NEWAPI_REFRESH_TOKEN"),
)
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.
The default browser fingerprint is Chrome. Choose another curl_cffi fingerprint or configure proxies by supplying your own curl_cffi.requests.Session:
from curl_cffi import requests
session = requests.Session(impersonate="safari")
client = NewAPI("https://newapi.example.com", session=session)
Authenticate with a browser session cookie
One-api style deployments without the token-rotation flow authenticate the dashboard through the gorilla session cookie plus the numeric New-Api-User header that their frontend sends on every request. Pass the cookie value copied from the browser as session_token; the client decodes the embedded user id automatically and replays both the cookie and the header:
import os
from newapi import NewAPI
client = NewAPI(
"https://oneapi.example.com",
session_token=os.environ["NEWAPI_SESSION_TOKEN"],
)
Instances with opaque cookies embed no user id; pass user_id explicitly in that case, or to override the embedded one. The cookie name defaults to session and can be changed with session_cookie. When the instance re-issues the session cookie, the client picks up the rotated value from Set-Cookie automatically. Session-cookie mode has no refresh flow: refresh() raises AuthenticationError, and once the server-side session expires a fresh cookie value must be extracted from the browser. logout() calls the fork's legacy POST /api/user/logout endpoint in this mode.
Log in with username and password
from newapi import NewAPI
with NewAPI("https://newapi.example.com") as client:
user = client.login("root", "password")
print(user.username, user.quota)
print(client.is_authenticated)
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:
client.login("root", "password", turnstile_token="captcha-proof")
For a TOTP-enabled account, login() raises TwoFactorRequired and retains the flow token in memory:
from newapi import NewAPI, TwoFactorRequired
client = NewAPI("https://newapi.example.com")
try:
client.login("root", "password")
except TwoFactorRequired:
client.complete_2fa("123456")
Common operations
Resources are callable for their common list operation and also expose explicit methods.
balance = client.balance()
print(balance.quota, balance.amount)
status = client.status()
groups = client.groups()
print(groups["vip"].ratio, groups["vip"].desc)
models = client.account.models()
print(client.account.aff_code())
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).
Gateway tokens
tokens and keys refer to the same resource. Instances return masked key values in list responses; call reveal() to fetch the full sk-... value.
first_page = client.tokens(page_size=50)
for token in first_page:
print(token.id, token.name, token.status, token.remain_quota)
all_tokens = client.tokens.all()
client.tokens.create("automation", group="default")
token, key = client.tokens.create_and_reveal("automation", group="default")
client.tokens.update(token.id, name="nightly automation")
client.tokens.disable(token.id)
client.tokens.enable(token.id)
client.tokens.delete(token.id)
print(client.tokens.reveal(token.id))
print(client.tokens.reveal_batch([1, 2, 3]))
print(client.tokens.auto_groups())
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.
Usage history
history, usage, and logs refer to the same resource.
from datetime import datetime, timedelta, timezone
end = datetime.now(timezone.utc)
start = end - timedelta(days=7)
page = client.history(
log_type="consume",
start_timestamp=start,
end_timestamp=end,
page_size=100,
)
for record in page:
print(record.created_at, record.model_name, record.quota, record.prompt_tokens)
for record in client.history.iter(log_type="consume", page_size=100):
process(record)
stats = client.logs.stat(log_type="consume", start_timestamp=start, end_timestamp=end)
print(stats.quota, stats.rpm, stats.tpm)
log_type accepts an integer or one of topup, consume, manage, system, error, refund, and login. Timestamps accept datetime objects or Unix seconds.
Dashboard data
rows = client.dashboard.quota_data(start_timestamp=start, end_timestamp=end)
flow = client.dashboard.flow_data(start_timestamp=start, end_timestamp=end)
Both endpoints limit the time span to one month; flow_data requires explicit positive bounds.
Top-up, redemption, and payment
Online payment is optional and must be enabled and configured by the instance administrator. Inspect the top-up configuration before offering a recharge:
info = client.topup.info()
if info.enable_stripe_topup:
link = client.payment.stripe_pay(10)
print(link)
if info.enable_online_topup:
amount = client.payment.epay_amount(10)
checkout = client.payment.epay_pay(10, "alipay")
print(checkout.url, checkout.params)
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:
orders = client.topup.orders()
result = client.topup.redeem("REDEMPTION-CODE")
print(result.quota)
Subscriptions
plans = client.subscriptions.plans()
overview = client.subscriptions.self()
client.subscriptions.set_preference("balance_first")
client.subscriptions.purchase_with_balance(plans[0].id)
Check-in
status = client.account.checkin_status()
if status.enabled:
result = client.account.checkin()
print(result.quota_awarded, result.checkin_date)
Login sessions
for entry in client.account.sessions():
print(entry.sid, entry.login_method, entry.current)
client.account.revoke_session("sid-from-another-device")
client.account.revoke_other_sessions()
These endpoints require a browser login session; long-lived system access tokens are rejected.
Fork-specific endpoints
request() provides the same authentication, envelope handling, refresh behavior, and error mapping for relative endpoints that are not part of the stable resource API.
result = client.request("GET", "user/self")
Absolute URLs and parent-path traversal are rejected so a session token cannot be redirected outside the configured API root.
Errors
HTTP failures and new-api envelope failures use typed exceptions:
from newapi import APIError, AuthenticationError, NewAPIError, RateLimitError
try:
client.tokens.create("automation")
except RateLimitError as error:
print(error.retry_after)
except AuthenticationError:
client.login("root", "password")
except NewAPIError as error:
print(error)
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.
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.
Release files for newapi-python 0.2.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 | |
|---|---|---|---|
| newapi_python-0.2.0.tar.gz | 28.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| newapi_python-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 51.5 kB
Release files / newapi_python-0.2.0.tar.gz
| Download URL | newapi_python-0.2.0.tar.gz |
|---|---|
| Size | 28.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f7ce102d0155333d321ea49215ad813f50242075f0eb6f423d5ba1cca252d920
|
|
BLAKE2b-256 checksum How to use checksums |
be0c4b2354b07d47476753d2589f0d7075e29a4d71196e5374db666ba9c7b451
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.0
|
Release files / newapi_python-0.2.0-py3-none-any.whl
| Download URL | newapi_python-0.2.0-py3-none-any.whl |
|---|---|
| Size | 23.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
76d1157a8f5e93b15d18edad29863c5110b7a3cfde351c669a57dc146337ebac
|
|
BLAKE2b-256 checksum How to use checksums |
c50f1cd2ff353f224765ef47788509187df49e6262d413424de71a62d72f851c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.0
|