norbix-python
Official Python SDK for Norbix. Use split clients with flat module access:
NorbixApifor API scope (client.database,client.membership, ...)NorbixHubfor Hub scope (client.database,client.account, ...)
Install
uv add norbix
Optional: load .env in apps with python-dotenv (load_dotenv() before constructing Norbix()).
Quickstart
from norbix_python import NorbixApi
# Service mode
norbix = NorbixApi(api_key="<api_key>", project_id="proj_123")
norbix.database.find("orders", take=20, skip=0, orderBy=[{"field": "createdAt", "direction": "desc"}])
# User mode
from norbix_python import LoginCredentials, NorbixApi
norbix = NorbixApi(project_id="proj_123")
norbix.login(LoginCredentials(user_name="alice@team.io", password="secret"))
norbix.database.find("orders", take=10)
Async client
from norbix_python import AsyncNorbix
async def main() -> None:
async with AsyncNorbix(api_key="...", project_id="proj_123") as client:
await client.api.echo.echo()
# asyncio.run(main())
Real-world examples
1) List recent orders (API scope)
from norbix_python import DatabaseFindResult, NorbixApi, NorbixError
norbix = NorbixApi(api_key="sk_live_xxx", project_id="proj_123")
try:
raw = norbix.database.find("orders", take=20, skip=0, orderBy=[{"field": "createdAt", "direction": "desc"}])
typed = DatabaseFindResult.model_validate(raw) if isinstance(raw, dict) else DatabaseFindResult()
items = typed.results
print(f"Fetched {len(items)} orders")
except NorbixError as exc:
print(exc.code, exc.status, exc.message)
2) Login as user and load profile
from norbix_python import LoginCredentials, NorbixApi
norbix = NorbixApi(project_id="proj_123")
auth = norbix.login(LoginCredentials(user_name="alice@team.io", password="secret"))
print("Logged in, token prefix:", str(auth.get("bearerToken", ""))[:16])
users = norbix.membership.get_users()
print("Users response:", users)
3) Account-scoped Hub call (requires account_id)
from norbix_python import NorbixHub
norbix = NorbixHub(
api_key="sk_live_xxx",
project_id="proj_123",
account_id="acc_456", # required for account-scoped endpoints
)
account = norbix.account.get_account_profile()
print(account)
Errors
from norbix_python import NorbixError
try:
norbix.files.get_file_info(integration_id, path="a/b.txt")
except NorbixError as exc:
# http_status / error_code are the names every Norbix SDK uses.
# status / code are the same values, kept for older code.
print(exc.http_status, exc.error_code, exc.message)
for item in exc.errors:
print(item.error_code, item.field_name, item.message)
print(exc.body) # the answer exactly as it arrived
message and error_code are the gateway's own. The gateway puts them inside
responseStatus.errors[], so the SDK reads that list first, takes the first
entry for the message and the code, and keeps every entry in errors. Only
when the body has no responseStatus are the top-level message and
errorCode read. Request failed (HTTP <status>) with the code
HTTP_<status> is the last fallback, used when the body says nothing — a 500
page that is not JSON, say.
Breaking change — a refused call now raises
The gateway answers a business refusal (an unknown id, a rule that says no)
with HTTP 200 and responseStatus.isSuccess = False. The SDK used to hand
that answer back as a normal value, so code carried on as if the call had
worked. It now raises a NorbixError with http_status 200 and the gateway's
message and error code.
If your code checked result["responseStatus"]["isSuccess"] itself, move that
check into a try / except. Endpoints that answer with raw bytes rather than a
document (file download, the public file link) are not JSON and are unchanged.
Both the sync and the async client follow the same rule.
Breaking changes (recent major-style refresh)
- Methods use snake_case (
find_one,get_database_schemas) instead of camelCase. - Path parameters are positional or keyword arguments (for example
find("orders", ...),find_one("orders", id)). Remaining query/body fields are passed as keyword args. - Use typed errors where helpful:
AuthenticationError,NotFoundError,RateLimitError,ValidationError(all subclassNorbixError).
Authentication
- API key: set
api_keyorNORBIX_API_KEY - JWT bearer: set
bearer_token,NORBIX_BEARER_TOKEN, or callnorbix.login(...) - If both are configured, bearer token wins
- If neither is configured, SDK raises
NORBIX_NOT_AUTHENTICATED
API keys and JWTs are sent as Authorization: Bearer ... (document your backend expectations).
Configuration from environment
NORBIX_API_KEY=sk_live_...
NORBIX_PROJECT_ID=proj_123
NORBIX_ACCOUNT_ID=acc_456
NORBIX_API_URL=https://api.norbix.ai
NORBIX_HUB_URL=https://hub.norbix.ai
NORBIX_REGION=nb-eu-germany
norbix = NorbixApi() # reads from environment when values omitted
Multi-region support
Norbix can run a project in one or more regions (region codes like
nb-eu-germany). The SDK has no default region: when no region is
configured, no region header is sent and the standard base URLs are used.
Selecting a region
Resolution order: explicit region= on the client → NORBIX_REGION
environment variable → unset (no header).
from norbix_python import Norbix
norbix = Norbix(api_key="sk_live_xxx", project_id="proj_123", region="nb-eu-germany")
region= is accepted by all clients: Norbix, NorbixApi, NorbixHub,
and AsyncNorbix. Every request then carries the nb-region header.
Switching at runtime
norbix.set_region("nb-eu-germany") # subsequent requests target this region
norbix.get_region() # "nb-eu-germany"
norbix.set_region(None) # clear — no nb-region header is sent
Available on the sync clients and AsyncNorbix alike.
Per-call override (header only)
The client.hub.regions methods accept a per-call region= that overrides
the client default for that request's nb-region header only — the
request URL is never changed by a per-call region:
norbix.hub.regions.list(region="nb-us-east")
Regional base URLs
When a region is set and you are using the SDK-default base URLs
(https://api.norbix.ai / https://hub.norbix.ai), the SDK prefixes the
region as a subdomain:
region="nb-eu-germany" → https://nb-eu-germany.api.norbix.ai
https://nb-eu-germany.hub.norbix.ai
Custom base URLs (base_url_api=, base_url_hub=, NORBIX_API_URL,
NORBIX_HUB_URL) are never rewritten — self-hosted and custom
deployments are unaffected; the nb-region header is still sent when a
region is configured.
Managing regions (Hub, account scope)
These endpoints require account_id (see
Project vs account scope).
from norbix_python import NorbixHub
norbix = NorbixHub(api_key="sk_live_xxx", project_id="proj_123", account_id="acc_456")
# Regions available to the account.
# Response shape: {"items": [{"id": ..., "continent": ..., "name": ...}, ...]}
# where "id" is the region code (e.g. "nb-eu-germany").
regions = norbix.regions.list()
# Update the regions a project runs in (omitted fields are left unchanged)
norbix.regions.update_project_regions(
"proj_123",
primary_region="nb-eu-germany",
additional_regions=["nb-us-east"],
)
# Pin a new project to regions at creation time
norbix.account.create_project(
name="my-project",
primary_region="nb-eu-germany",
additional_regions=["nb-us-east"],
)
With the combined client the same modules live under client.hub
(norbix.hub.regions.list(), norbix.hub.account.create_project(...)).
Async
from norbix_python import AsyncNorbix
async def main() -> None:
async with AsyncNorbix(
api_key="sk_live_xxx",
project_id="proj_123",
account_id="acc_456",
region="nb-eu-germany",
) as client:
regions = await client.hub.regions.list()
await client.hub.regions.update_project_regions(
"proj_123",
primary_region="nb-eu-germany",
region="nb-us-east", # per-call header override
)
client.set_region(None) # clear at runtime
Project vs account scope
project_idis required (set explicitly or via env).account_idis optional- Account-scoped Hub methods raise
NORBIX_ACCOUNT_SCOPE_REQUIREDifaccount_idis not configured
SDK maintenance
Regenerate API and Hub modules from DTO stubs:
uv run python scripts/generate_endpoints.py
This refreshes src/norbix_python/api/, hub/, matching tests under tests/api and tests/hub, and docs under docs/.
Development
uv sync
uv run ruff check .
uv run mypy src
uv run pytest
Releases
Pushes to main, next, and beta run
python-semantic-release
and publish to PyPI.
License
MIT
Release files for norbix 2.0.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 | |
|---|---|---|---|
| norbix-2.0.0.tar.gz | 297.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| norbix-2.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 351.7 kB
Release files / norbix-2.0.0.tar.gz
| Download URL | norbix-2.0.0.tar.gz |
|---|---|
| Size | 297.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
886316966dc6efa796d8a8e55558533e917a7c07d1024b4c728501ad8e4b146f
|
|
BLAKE2b-256 checksum How to use checksums |
f0f4ba01805985cbd14eb3d536852eb7dc7720978540a66ad3ea3672630c72a8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / norbix-2.0.0-py3-none-any.whl
| Download URL | norbix-2.0.0-py3-none-any.whl |
|---|---|
| Size | 54.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
edf7f44747a130bd4041665844940ca7b0387a89c6ef365dd3b2811a99a7930a
|
|
BLAKE2b-256 checksum How to use checksums |
af6a56f6d3d5a1702983b9a5f5b39131ab487a4a8a1720448e921c443d53e2ea
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|