aisha-ai is the Python SDK for the Aisha AI API.
Use it when you want to add text-to-speech or speech-to-text to a Python app, backend service, script, or automation.
from aisha_ai import AishaClient
client = AishaClient(api_key="your-api-key")
result = client.tts(transcript="Salom dunyo")
print(result["audioUrl"])- Features
- Requirements
- Install
- Quick Start
- API Versions
- Server Integration Flow
- Client Setup
- Text-to-Speech
- Speech-to-Text
- History
- Parameter Reference
- SDK Constants
- Error Handling
- Optional CLI
- Development
- Continuous Integration
- Publishing
- Official API Docs
- Text-to-speech (TTS)
- Speech-to-text (STT)
- TTS and STT history
- Sync TTS requests
- Async TTS requests with webhook callbacks
- Clean Python exceptions for API and network errors
- No runtime dependencies outside the Python standard library
- Python 3.8 or newer
- An Aisha AI API key
Create an API key at space.aisha.group.
pip install aisha-aiFor local development from this repository:
python -m pip install -e .Set your API key:
export AISHA_API_KEY="your-api-key"Use the SDK:
import os
from aisha_ai import AishaClient
client = AishaClient(api_key=os.environ["AISHA_API_KEY"])
result = client.tts(transcript="Salom dunyo")
print(result["audioUrl"])This SDK currently targets these Aisha API versions:
| Feature | API version | SDK methods |
|---|---|---|
| TTS sync and async | API v1 | tts(), tts_status(), tts_history() |
| STT short-audio sync | API v1 | stt(), stt_history() |
The Aisha API also documents STT API v2 for long-audio async transcription.
The client defaults to api_version="v1", but the version is configurable:
client = AishaClient(api_key="your-api-key", api_version="v2")You can also pass api_version=2; the SDK normalizes it to "v2". Existing
SDK methods then call /api/v2/... paths. Only switch versions for endpoints
that are supported by the Aisha API version you are integrating with.
For server-to-server traffic, Aisha uses the X-Api-Key header. The SDK sends
this header for every request:
X-Api-Key: your-api-keyRecommended backend integration flow:
- Create an API key in Space.
- Send a small test TTS or STT request.
- Confirm the response shape your app needs.
- For async TTS, store the returned
idortask_id. - Use status and history endpoints to cover the full workflow.
With the SDK, that flow looks like this:
from aisha_ai import AishaClient
client = AishaClient(api_key="your-api-key")
queued = client.tts(
transcript="Webhook orqali qaytadigan sinov matni.",
webhook_url="https://example.com/webhooks/tts",
)
status = client.tts_status(queued["id"])
history = client.tts_history(page=1, limit=10)Create a client:
from aisha_ai import AishaClient
client = AishaClient(api_key="your-api-key")Set the response language for API messages:
client = AishaClient(api_key="your-api-key", language="uz")Use a custom API base URL:
client = AishaClient(
api_key="your-api-key",
base_url="https://back.aisha.group",
)Use a different API version:
client = AishaClient(
api_key="your-api-key",
api_version="v2",
)Change request timeout:
client = AishaClient(api_key="your-api-key", timeout=60)By default, TTS returns the generated audio URL. It does not download the file:
result = client.tts(transcript="Assalomu alaykum")
print(result["audioUrl"])Pass output_path when you want the SDK to download the generated audio for
you:
result = client.tts(
transcript="Assalomu alaykum",
output_path="outputs/assalomu-alaykum.wav",
)
print(result["audioUrl"])
print(result["output_path"])The SDK creates parent folders when needed. If you do not pass output_path,
the SDK only returns the URL and does not write anything to disk.
When downloading, the SDK sends the same API key header plus a normal SDK
User-Agent, so protected audio URLs can be fetched from backend services and
CI jobs.
You can also download an existing audio URL later:
client.download_audio(
url=result["audioUrl"],
output_path="outputs/from-url.wav",
)For Uzbek TTS, you can pass model, mood, and speed:
result = client.tts(
transcript="Assalomu alaykum",
language="uz",
model="Gulnoza",
mood="Happy",
speed=1.0,
)
print(result["audioUrl"])Known mood values:
NeutralCheerfulHappySad
Default model:
Gulnoza
Speed:
0uses the API default speed0.5is slower1.0is normal speed2.0is faster
The SDK sends model, mood, and speed only when language="uz".
result = client.tts(
transcript="Hello",
language="en",
)result = client.tts(
transcript="Privet",
language="ru",
)Pass webhook_url when you want the API to process TTS in the background:
queued = client.tts(
transcript="Salom dunyo",
webhook_url="https://example.com/aisha-webhook",
)
print(queued["id"])
print(queued["status"])Check the task later:
status = client.tts_status(queued["id"])
print(status)Use output_path only for sync TTS. Async TTS returns task information first,
so there is no completed audio file to download immediately.
result = client.stt(file="meeting.wav")
print(result["transcript"])with open("meeting.wav", "rb") as audio:
data = audio.read()
result = client.stt(file=data, filename="meeting.wav")
print(result["transcript"])Use diarization when you want speaker separation:
result = client.stt(
file="meeting.wav",
diarization=True,
)When diarization is enabled, the API expects audio to be at least 15 seconds long.
List past TTS requests:
tts_history = client.tts_history(page=1, limit=10)List past STT requests:
stt_history = client.stt_history(page=1, limit=10)page and limit must be positive integers.
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key |
str |
required | API key from space.aisha.group. |
base_url |
str |
https://back.aisha.group |
API base URL. |
api_version |
str | int |
v1 |
API version used in endpoint paths. |
language |
str | None |
None |
API message language: uz, en, or ru. |
timeout |
float |
120.0 |
Request timeout in seconds. |
| Parameter | Type | Default | Description |
|---|---|---|---|
transcript |
str |
required | Text to turn into speech. Max 1000 characters. |
language |
str |
uz |
Voice language: uz, en, or ru. |
model |
str |
Gulnoza |
Uzbek TTS voice model. Sent only for language="uz". |
mood |
str |
Neutral |
Uzbek TTS mood. See SDK Constants. |
speed |
float | str |
1.0 |
Uzbek TTS speed. Use 0, or a value from 0.5 to 2.0. |
webhook_url |
str | None |
None |
Webhook URL for async TTS. |
output_path |
str | path | None |
None |
Local path where audio should be saved. |
| Parameter | Type | Default | Description |
|---|---|---|---|
id |
int | str |
required | Async TTS task ID. |
| Parameter | Type | Default | Description |
|---|---|---|---|
url |
str |
required | Full audio URL to download. |
output_path |
str or path |
required | Local path where audio should be saved. |
| Parameter | Type | Default | Description |
|---|---|---|---|
file |
str, bytes, path, or binary file object |
required | Audio file to transcribe. |
language |
str |
uz |
Audio language: uz, en, or ru. |
diarization |
bool |
False |
Enables speaker diarization. |
filename |
str | None |
None |
File name used in upload. Useful when passing raw bytes. |
| Parameter | Type | Default | Description |
|---|---|---|---|
page |
int |
1 |
Page number. Must be positive. |
limit |
int |
10 |
Rows per page. Must be positive. |
You can import common values from the package:
from aisha_ai import (
DEFAULT_API_VERSION,
DEFAULT_TTS_MODEL,
DEFAULT_TTS_MOOD,
DEFAULT_TTS_SPEED,
MAX_TTS_TRANSCRIPT_LENGTH,
STT_API_VERSION,
SUPPORTED_AUDIO_FORMATS,
SUPPORTED_LANGUAGES,
TTS_API_VERSION,
TTS_MOODS,
)
print(SUPPORTED_LANGUAGES)
print(TTS_MOODS)
print(DEFAULT_API_VERSION)
print(TTS_API_VERSION)Current values:
| Name | Value |
|---|---|
DEFAULT_API_VERSION |
"v1" |
SUPPORTED_LANGUAGES |
{"uz", "en", "ru"} |
TTS_API_VERSION |
"v1" |
STT_API_VERSION |
"v1" |
SUPPORTED_AUDIO_FORMATS |
("mp3", "wav", "ogg", "m4a") |
TTS_MOODS |
("Neutral", "Cheerful", "Happy", "Sad") |
DEFAULT_TTS_MODEL |
"Gulnoza" |
DEFAULT_TTS_MOOD |
"Neutral" |
DEFAULT_TTS_SPEED |
1.0 |
MIN_TTS_SPEED |
0.5 |
MAX_TTS_SPEED |
2.0 |
MAX_TTS_TRANSCRIPT_LENGTH |
1000 |
The SDK raises AishaApiError when the API returns an error response:
from aisha_ai import AishaApiError, AishaClient
client = AishaClient(api_key="your-api-key")
try:
result = client.tts(transcript="Salom")
except AishaApiError as error:
print(error.status)
print(error.body)
print(error.url)Network failures raise AishaConnectionError. It is a subclass of
AishaApiError, so one except AishaApiError block can handle both API and
network failures.
For connection errors:
error.statusis0error.bodyisNone
The SDK also raises normal Python validation errors before making a request:
TypeErrorfor missing or wrong input typesValueErrorfor invalid values, such as unsupported language or invalid page
The package also installs an aisha-ai command. It is useful for quick manual
tests, demos, or simple scripts. For applications, prefer importing
AishaClient in Python code.
Set your API key:
export AISHA_API_KEY="your-api-key"Generate speech:
aisha-ai tts "Salom dunyo" --out salom.wavGenerate Uzbek TTS with options:
aisha-ai tts "Assalomu alaykum" --model Gulnoza --mood Happy --speed 1.2Run async TTS:
aisha-ai tts "Salom dunyo" --webhook https://example.com/aisha-webhook --jsonTranscribe audio:
aisha-ai stt meeting.wavEnable diarization:
aisha-ai stt meeting.wav --diarizationView history:
aisha-ai history tts --page 1 --limit 10
aisha-ai history stt --page 1 --limit 10Print raw JSON:
aisha-ai history tts --jsonUse a key without setting an environment variable:
aisha-ai tts "Salom" --api-key "your-api-key"Run the test suite:
python -m unittest discover -s tests -vThe tests use an in-process mock API server. They do not call the real Aisha AI API and do not need a real API key.
Install build tools:
python -m pip install -e ".[dev]"Pull requests and pushes to main run GitHub Actions CI.
The test job checks:
- package installation
- Python syntax compilation
- unit tests with the local mock API server
- Python 3.8 through Python 3.13
The quality job checks:
- lint with Ruff
- formatting with Ruff format
- package type checking with mypy
The package job checks:
- wheel build
- source distribution build
- package metadata and README rendering with
twine check
The real API smoke test job runs after quality checks, unit tests, and package
build. It uses the repository secret AISHA_API_TEST_KEY and checks:
- a few short TTS requests with different Uzbek options
- downloading one generated audio file with
output_path - TTS history response shape
- a few edge cases
If AISHA_API_TEST_KEY is missing, the real API tests are skipped.
Publishing is separate from normal merges:
- Pull requests test the code before merge.
- Pushes to
maintest and build the package. - Version tags like
v1.0.1publish to PyPI after CI passes. - The PyPI publish job uses the GitHub secret
PYPI_API_TOKEN. - The publish job uses the protected GitHub environment named
pypi.
This repository is set up for CI-based publishing. You should not upload files from your laptop for normal releases.
Create a PyPI API token:
- Log in to PyPI.
- Open Account settings -> API tokens.
- Create a token named
aisha-python-github-actions. - For the first publish, use an account-scoped token because the
aisha-aiproject does not exist yet. - Add the token to this repository as the GitHub Actions secret
PYPI_API_TOKEN.
After the first successful publish, replace the account-scoped token with a
project-scoped token for aisha-ai.
Then configure the GitHub environment:
- Open the repository on GitHub.
- Go to Settings -> Environments.
- Create an environment named
pypi. - Add required reviewers if you want a manual approval before publishing.
- Allow deployments only from tags that match
v*.
Before releasing:
- Update
versioninpyproject.toml. - Update
__version__insrc/aisha_ai/client.py. - Open a pull request.
- Wait for CI to pass.
- Merge to
main. - Create and push a matching version tag.
Example:
git checkout main
git pull
git tag v1.0.1
git push origin v1.0.1The tag starts CI again. If tests and package checks pass, the publish job uploads the package to PyPI.
Build the package:
python -m buildCheck the package:
python -m twine check dist/*Upload to TestPyPI manually if needed:
python -m twine upload --repository testpypi dist/*Upload to PyPI manually only if CI publishing is unavailable:
python -m twine upload dist/*- Aisha AI: https://aisha.group
- API documentation: https://aisha.group/en/api-documentation
- API keys: https://space.aisha.group