Skip to main content

Python SDK

Status: not published yet. nexspace is generated by Stainless from the merged OpenAPI spec and stainless.config.yml; the first release has not landed on PyPI. The hand-written package under packages/sdk-python/ is a deprecated stopgap carrying the Private :: Do Not Upload classifier so it can never be uploaded over the canonical package — it is not what this page documents. Track tools/stainless/README.md for the release.

Installation

Requires Python 3.9+.

Quick Start

Configuration

There is no version argument. NexSpace-Version is a per-request header (see Pinning an API version), not a constructor argument — a client-level default would silently pin every caller in your process to one date.

Resources

The generated resources mirror stainless.config.yml. Path parameters are positional; query and body fields are keyword arguments in snake_case.

Facilities

update needs facilities:write. create is guarded by role, not scope — authorize(ROLES.SUPER_ADMIN) against the key owner’s role — so it only succeeds for a key owned by a super admin.

Staff

GET /api/staff accepts exactly four filters — facility_id, specialty, is_active, and search (name or email). There is no query field and no limit.

Staff credentials

Credentials hang off a staff member, as the staff.credentials subresource:
Each credential carries status — one of active, expiring, expired, pending, rejected — so filter client-side on that plus expiration_date to find what is lapsing. There is no server-side “expiring credentials” REST endpoint; the MCP verb listExpiringCredentials covers that shape over MCP.

Shifts

status accepts open, assigned, in_progress, completed, or cancelled. shifts.unassign and shifts.delete are generated too.

Agent runs

Requires the agents:run scope. A second concurrent start for the same agent returns 409 AGENT_BUSY. agents.list_runs, agents.cancel_run, and agents.list_run_approvals round out the resource. The SSE progress stream (GET /api/agents/{id}/runs/{runId}/stream) is not generated — consume it with the CLI or raw HTTP. See Agent runs.

Approvals

Two gates, not one: the credential needs agents:approve and must own the run that raised the approval — and because that makes every decision a self-approval, the credential’s bound user must also hold the ai.approve_actions RBAC permission. Without it you get 403 SELF_APPROVAL_FORBIDDEN.

Everything else

Client-level calls

whoami() returns the identity the presented credential authenticates as — the fastest way to confirm a key is live and bound to the user you expect.
No api_keys resource is generated. /api/api-keys* rejects every API-key-authenticated request with 403 FORBIDDEN (“API keys cannot be managed with an API key — sign in to the dashboard”) before the handler runs, so the methods would be guaranteed-dead code. Mint and rotate keys in the dashboard under Settings → API Keys.No mcp resource either. MCP is spoken over JSON-RPC by MCP clients, and the SDK is pinned to https://api.nexspace365.com, where every /mcp path answers 403 MCP_HOST_NOT_ALLOWED. Point an MCP client at https://mcp.nexspace365.com instead.

Typed models

Responses are typed models generated from the OpenAPI schemas, so attribute access and IDE autocomplete work:
The model names follow the schemas in stainless.config.yml — Facility, Staff, Shift, Credential, WebhookSubscription, WebhookEvent, DashboardStats, ApprovalResolution.

Pinning an API version

Send NexSpace-Version as a per-request header. Omit it and you get the latest version.
2026-07-24 is the current latest. Discover the catalog with client.api_versions(), and see Versioning.

Error Handling

The generated client raises an exception hierarchy rooted at APIStatusError, one class per HTTP status family:
Every NexSpace error body has the same envelope, so e.body is:
Quote requestId when you email admin@nexspace365.com. See Errors for the full code list.

Idempotency

Mutations are not given an automatic key. Pass one yourself with the idempotency_key= request option, which sends the Idempotency-Key header:
Replaying the same key with the same body within 24 hours replays the original response; the same key with a different body returns 409 Conflict. See Idempotency.

Async Support

Every resource and method above has an async twin on AsyncNexSpace (default_client_name is pinned to NexSpace in stainless.config.yml, so the async class is named AsyncNexSpace, not AsyncNexspace):
The async client takes the same options (base_url, max_retries=2, timeout=60.0) and raises the same APIStatusError hierarchy.