Skip to main content

norbix-python

CI PyPI Python License

Official Python SDK for Norbix. Use split clients with flat module access:

  • NorbixApi for API scope (client.database, client.membership, ...)
  • NorbixHub for 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 subclass NorbixError).

Authentication

  • API key: set api_key or NORBIX_API_KEY
  • JWT bearer: set bearer_token, NORBIX_BEARER_TOKEN, or call norbix.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_id is required (set explicitly or via env).
  • account_id is optional
  • Account-scoped Hub methods raise NORBIX_ACCOUNT_SCOPE_REQUIRED if account_id is 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)

Source distribution for norbix 2.0.0
File Size Uploaded
norbix-2.0.0.tar.gz 297.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for norbix 2.0.0
File Interpreter ABI Platform
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}

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 release files

1.2.0

2 release files

1.1.1

2 release files

1.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