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"),
    user_id=int(os.environ["NEWAPI_USER_ID"]),
)

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. Access-token authentication additionally requires user_id: new-api instances verify the numeric New-Api-User header on every authenticated request and reject requests without it with 401 Unauthorized, New-Api-User header not provided. The client sends the header automatically from user_id, and login() and refresh() capture the id from the instance's responses. Such tokens cannot refresh browser sessions on their own.

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.3.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.3.0
File Size Uploaded
newapi_python-0.3.0.tar.gz 34.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for newapi-python 0.3.0
File Interpreter ABI Platform
newapi_python-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 58.2 kB

Release files / newapi_python-0.3.0.tar.gz

Download URL newapi_python-0.3.0.tar.gz
Size 34.4 kB
Tags Source
SHA-256 checksum
How to use checksums
1eb07262fd8c354ab50b50cc4469112ca66c973d2b1d8ebf16409f5001ae54cf
BLAKE2b-256 checksum
How to use checksums
caef1b6482e166de80584faa873972728209198726dd121d77817eb1cc092d4e
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.3.0-py3-none-any.whl

Download URL newapi_python-0.3.0-py3-none-any.whl
Size 23.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
89d7ec9c57a140e41bd08272b70a71a4a5fcfa9d69955936e92856aab3d4ac9a
BLAKE2b-256 checksum
How to use checksums
f3d70e0eb214c54f4bfa613297ea828c24e7e0549af77888eac4b71015a90433
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

This release

0.3.0 This release

2 release files

0.2.0

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