LIVE · AUDIT-CHAINED · EU-RESIDENT
SYSTEM · 99.99% UPTIME
v 1.0 ↗ MADE IN EU

nexbasira (Python)

Server-side Python SDK. Same resource surface as the Node SDK, requests-backed for transparent retries, mockable Session for tests.

Install

pip install nexbasira

Requires Python 3.10+.

Initialise

from nexbasira import NexBasira

nb = NexBasira(
    api_key=os.environ["NB_PUBLIC_KEY"],
    api_secret=os.environ["NB_SECRET_KEY"],
    # base_url="https://app.nexbasira.com/api/v1/public",  # default
    # timeout=30,                                              # default
)

Resources

nb.sessions       # create / list / retrieve / end / invite
nb.evidence       # list / retrieve / signed download URL
nb.whiteboards    # list per session
nb.webhooks       # register / rotate_secret / test_fire / construct_event
nb.branding       # read-only
nb.org            # read-only

Common patterns

Create + invite

session = nb.sessions.create(
    notes="Vehicle damage claim CL-2026-0042",
    scheduled_for="2026-05-23T10:00:00Z",
    locale="fr",
)

invite = nb.sessions.invite(
    session.id,
    recipient_email="alex@policyholder.com",
    send_email=True,
)

print(invite.url)  # shown ONCE

Iterator pagination

# Auto-pages through all sessions:
for session in nb.sessions.iter(limit=50):
    print(session.id, session.status)

# Or one page at a time if you want pagination control:
page = nb.sessions.list_page(limit=25)
# page.data, page.has_more, page.next_cursor

Idempotent POST

import uuid

session = nb.sessions.create(
    notes="...",
    idempotency_key=str(uuid.uuid4()),
)

Verifying a webhook (Flask)

from flask import Flask, request, abort
from nexbasira import NexBasira, InvalidSignatureError

app = Flask(__name__)
nb = NexBasira(api_key="...", api_secret="...")

@app.post("/nb-webhook")
def webhook():
    sig = request.headers.get("NB-Signature", "")
    secret = os.environ["NB_WEBHOOK_SECRET"]
    try:
        # IMPORTANT: pass request.data (raw bytes), NOT request.get_json()
        event = nb.webhooks.construct_event(request.data, sig, secret)
    except InvalidSignatureError:
        abort(401, "bad signature")

    if event.type == "session.completed":
        on_completed(event.data)
    elif event.type == "audit.anchored":
        on_anchored(event.data)
    return "", 204

FastAPI / async

The SDK is sync by design (no async def on the resource methods). In FastAPI handlers, call it from a run_in_threadpool or use anyio.to_thread.run_sync():

from fastapi import FastAPI, Request, HTTPException
from anyio.to_thread import run_sync
from nexbasira import InvalidSignatureError

app = FastAPI()

@app.post("/nb-webhook")
async def webhook(req: Request):
    body = await req.body()
    sig = req.headers.get("nb-signature", "")
    try:
        event = await run_sync(
            nb.webhooks.construct_event, body, sig, WEBHOOK_SECRET,
        )
    except InvalidSignatureError:
        raise HTTPException(401, "bad signature")
    return {"ok": True}

Typed errors

from nexbasira import (
    AuthenticationError,
    PermissionError,
    NotFoundError,
    RateLimitError,
    InvalidSignatureError,
    NexBasiraError,
)

try:
    nb.sessions.create(...)
except RateLimitError as e:
    time.sleep(e.retry_after_seconds)
    # retry
except NexBasiraError as e:
    log.warning("nb error: %s (status=%d)", e.code, e.status)
    raise

Testing — mockable Session

The SDK uses a requests.Session under the hood. Pass your own (or a mock) via the http_session kwarg to intercept in tests:

from unittest.mock import MagicMock
from nexbasira import NexBasira

def test_my_handler():
    session = MagicMock()
    session.request.return_value.status_code = 201
    session.request.return_value.json.return_value = {"id": "sess-1", "status": "created", ...}
    nb = NexBasira(api_key="x", api_secret="y", http_session=session)

    s = nb.sessions.create(notes="test")
    assert s.id == "sess-1"
    session.request.assert_called_once()

Typed models

Generated from the OpenAPI spec via datamodel-code-generator; importable as dataclasses:

from nexbasira import Session, Evidence, WebhookEvent

def on_completed(session: Session) -> None:
    ...

What's next