EN DIRECT · AUDIT CHAÎNÉ · ÉDR UE
SYSTÈME · 99,99% DISPONIBILITÉ
v 1.0 ↗ FAIT EN UE

nexbasira (Python)

SDK Python côté serveur. Même surface de ressources que le SDK Node, basé sur requests pour des nouvelles tentatives transparentes, Session mockable pour les tests.

Installation

pip install nexbasira

Nécessite Python 3.10+.

Initialisation

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
)

Ressources

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

Patterns courants

Créer + inviter

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

Pagination par itérateur

# 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

POST idempotent

import uuid

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

Vérifier un 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

Le SDK est synchrone par conception (pas d'async def sur les méthodes de ressource). Dans les handlers FastAPI, appelez-le depuis un run_in_threadpool ou utilisez 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}

Erreurs typées

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

Tests — Session mockable

Le SDK utilise une requests.Session en interne. Passez la vôtre (ou un mock) via le kwarg http_session pour intercepter dans les 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()

Modèles typés

Générés depuis la spécification OpenAPI via datamodel-code-generator ; importables comme dataclasses :

from nexbasira import Session, Evidence, WebhookEvent

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

Et ensuite