Skip to main content

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)

Source distribution for newapi-python 0.2.0
File Size Uploaded
newapi_python-0.2.0.tar.gz 28.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for newapi-python 0.2.0
File Interpreter ABI Platform
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

Release history Release notifications | RSS feed

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.0

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