Nexara Python SDK
Python SDK for the Nexara speech-to-text API: transcription, speaker diarization, speaker role tagging, structured LLM post-processing, and account billing. Full API documentation lives at docs.nexara.ru.
Requires Python 3.10+.
pip install nexara
Quickstart
from nexara import Nexara
client = Nexara(api_key="...") # or set NEXARA_API_KEY
text = client.transcriptions.create(file="audio.mp3").text
Pass exactly one of file= (path, bytes, or a binary file object — paths are
streamed from disk, not loaded into memory) or url=.
Diarization
call = client.transcriptions.create(file="call.mp3", task="diarize")
for segment in call.segments:
print(f"{segment.speaker}: {segment.text}")
Add meaningful speaker labels with roles — "auto" lets the model invent
labels, a list restricts them, a dict adds descriptions:
call = client.transcriptions.create(
file="call.mp3",
task="diarize",
roles=["client", "agent"],
)
Emotions
emotions=True attaches an emotion to each diarized segment — label (one of
angry, sad, neutral, positive), confidence, and the full probs
distribution when the server sends it:
call = client.transcriptions.create(
file="call.mp3",
task="diarize",
model="nexara-ru",
emotions=True,
)
for segment in call.segments:
if segment.emotion:
print(segment.speaker, segment.emotion.label, segment.emotion.confidence)
The scoring runs inside the ASR model, so it requires task="diarize",
model="nexara-ru" and a JSON response format; anything else raises
NexaraValidationError before the upload. Not every segment can be scored, so
check segment.emotion rather than assuming it is there. It carries a
per-second surcharge, charged only when emotion was actually returned.
Long audio: deferred jobs
create_job() submits the audio and returns immediately; the result is fetched
by polling. A failed job is never billed, so resubmitting is free.
job = client.transcriptions.create_job(file="long_recording.mp3")
result = job.wait() # polls; default timeout 1800s
# ...or pick it up later, even from another process:
job = client.transcriptions.retrieve_job(job_id)
Job results live for 12 hours from creation; up to 200 jobs may be in progress
per API key. In this SDK "async" always means asyncio — the deferred mode is
create_job(), not AsyncNexara.
LLM post-processing
Pass prompt= to run an LLM over the transcript, and optionally json_schema=
to force structured output:
result = client.transcriptions.create(
file="meeting.mp3",
prompt="Summarize the key decisions",
json_schema={"type": "object", "properties": {"decisions": {"type": "array"}}},
)
print(result.llm_output) # dict, validated against your schema
print(result.transcription.text) # the transcript it was derived from
Balance and usage
client.billing reports what is on the account and what it has been spent on.
Both endpoints cover the whole account, not just the key you authenticate with:
balance = client.billing.balance()
print(balance.balance, balance.currency, balance.rate_per_min)
# One page of billed calls, newest first.
page = client.billing.usage(limit=20)
for item in page.items:
print(item.timestamp, item.task, item.cost, item.api_key.name)
# ...or let the SDK walk the pages. History is unbounded — bound it.
for item in client.billing.iter_usage(max_items=200):
print(item.request_id, item.seconds, item.cost)
Paging is keyset-based, not offset-based: pass a page's next_cursor as
cursor= to get the next (older) page, so calls arriving mid-walk cannot shift
rows across a page boundary. item.cost is None — not 0 — for rows written
before per-request costs were recorded, and rate_per_min covers plain
transcription only (profanity_filter, roles, emotions and prompt are
surcharges on top of it).
asyncio
AsyncNexara is the same interface under await:
from nexara import AsyncNexara
async with AsyncNexara() as client:
result = await client.transcriptions.create(file="audio.mp3")
print(result.text)
Errors and validation
Requests that the server would reject — or, worse, accept, charge for, and
silently do something else with — fail client-side with NexaraValidationError
before any network call. Server errors map to typed exceptions by status code:
from nexara import NexaraValidationError, InsufficientBalanceError, RateLimitError
try:
result = client.transcriptions.create(file="audio.mp3")
except InsufficientBalanceError as e: # 402
print(e.detail)
429 and connection/timeout failures are retried with exponential backoff
(honoring Retry-After). 500 is deliberately not retried: on the
synchronous path the request may already have been billed, so a blind retry
could pay twice. Deferred jobs bill only on success, which makes create_job()
the safe path for retry-heavy workloads.
Not yet available
- Realtime streaming — the protocol is not yet public;
client.realtimeraisesNotImplementedErrorfor now. - Webhooks — job results are fetched by polling.
Development
The package is fully typed (py.typed, mypy strict). Offline tests
(pytest, no network needed) and runnable examples live in the repository;
NEXARA_USE_MOCK=1 runs everything against an in-memory mock transport.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nexara-0.5.0.tar.gz.
File metadata
- Download URL: nexara-0.5.0.tar.gz
- Upload date:
- Size: 47.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9550e0237d3deb88472eb614a13b4efd42a464a61840c8dd779485de73f19b09
|
|
| MD5 |
13d9ed7884cf31d095c76f6dcde50c0e
|
|
| BLAKE2b-256 |
cce712e4b2fb60ef1757bcbe4f91ed684e4dda4bcc968e8247b61795e4c7a9ef
|
Provenance
The following attestation bundles were made for nexara-0.5.0.tar.gz:
Publisher:
publish.yml on rootint/nexara-python-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nexara-0.5.0.tar.gz -
Subject digest:
9550e0237d3deb88472eb614a13b4efd42a464a61840c8dd779485de73f19b09 - Sigstore transparency entry: 2313502350
- Sigstore integration time:
-
Permalink:
rootint/nexara-python-sdk@f73d8e7f60ec45d53d98472d4615f2deb70278d5 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/rootint
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f73d8e7f60ec45d53d98472d4615f2deb70278d5 -
Trigger Event:
release
-
Statement type:
File details
Details for the file nexara-0.5.0-py3-none-any.whl.
File metadata
- Download URL: nexara-0.5.0-py3-none-any.whl
- Upload date:
- Size: 42.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf50c75ccfe1c9e18ef8cb8e5ff71ddabd2070176ce0f25057603d17bafd7ba1
|
|
| MD5 |
2f658c357ca089549f7e61cf633adc60
|
|
| BLAKE2b-256 |
a88c572366445bdb0b31a25a842198cf4d60ae83ee5e985cf09acb09cd392909
|
Provenance
The following attestation bundles were made for nexara-0.5.0-py3-none-any.whl:
Publisher:
publish.yml on rootint/nexara-python-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nexara-0.5.0-py3-none-any.whl -
Subject digest:
bf50c75ccfe1c9e18ef8cb8e5ff71ddabd2070176ce0f25057603d17bafd7ba1 - Sigstore transparency entry: 2313502353
- Sigstore integration time:
-
Permalink:
rootint/nexara-python-sdk@f73d8e7f60ec45d53d98472d4615f2deb70278d5 -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/rootint
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f73d8e7f60ec45d53d98472d4615f2deb70278d5 -
Trigger Event:
release
-
Statement type: