diff --git a/README.md b/README.md
index 7291477..b6c5d9f 100644
--- a/README.md
+++ b/README.md
@@ -44,8 +44,10 @@ client = Speechify(
token="YOUR_TOKEN",
)
client.tts.audio.speech(
- input="input",
- voice_id="voice_id",
+ audio_format="mp3",
+ input="Hello! This is the Speechify text-to-speech API.",
+ model="simba-english",
+ voice_id="george",
)
```
@@ -65,8 +67,10 @@ client = AsyncSpeechify(
async def main() -> None:
await client.tts.audio.speech(
- input="input",
- voice_id="voice_id",
+ audio_format="mp3",
+ input="Hello! This is the Speechify text-to-speech API.",
+ model="simba-english",
+ voice_id="george",
)
diff --git a/poetry.lock b/poetry.lock
index 1a4242d..0474c73 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -38,13 +38,13 @@ trio = ["trio (>=0.26.1)"]
[[package]]
name = "certifi"
-version = "2026.4.22"
+version = "2026.6.17"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.7"
files = [
- {file = "certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a"},
- {file = "certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580"},
+ {file = "certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db"},
+ {file = "certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432"},
]
[[package]]
@@ -133,13 +133,13 @@ zstd = ["zstandard (>=0.18.0)"]
[[package]]
name = "idna"
-version = "3.13"
+version = "3.15"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.8"
files = [
- {file = "idna-3.13-py3-none-any.whl", hash = "sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3"},
- {file = "idna-3.13.tar.gz", hash = "sha256:585ea8fe5d69b9181ec1afba340451fba6ba764af97026f92a91d4eef164a242"},
+ {file = "idna-3.15-py3-none-any.whl", hash = "sha256:048adeaf8c2d788c40fee287673ccaa74c24ffd8dcf09ffa555a2fbb59f10ac8"},
+ {file = "idna-3.15.tar.gz", hash = "sha256:ca962446ea538f7092a95e057da437618e886f4d349216d2b1e294abfdb65fdc"},
]
[package.extras]
diff --git a/pyproject.toml b/pyproject.toml
index d29a471..2615901 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,9 @@
+[project]
+name = "speechify-api"
+
[tool.poetry]
name = "speechify-api"
-version = "1.2.3"
+version = "1.2.4"
description = "Official Speechify API SDK"
readme = "README.md"
authors = [
@@ -36,7 +39,7 @@ packages = [
{ include = "speechify", from = "src"}
]
-[tool.poetry.urls]
+[project.urls]
Documentation = 'https://docs.speechify.ai/api-reference'
Homepage = 'https://docs.speechify.ai'
Repository = 'https://github.com/speechifyinc/speechify-api-sdk-python'
diff --git a/reference.md b/reference.md
index 14e9f47..fb5f4ee 100644
--- a/reference.md
+++ b/reference.md
@@ -12,7 +12,9 @@
-
-Gets the speech data for the given input
+Synthesize speech audio from text or SSML. Returns the complete audio
+file plus billing and speech-mark metadata in a single response. For
+low-latency playback or long-form text, use POST /v1/audio/stream.
@@ -33,8 +35,10 @@ client = Speechify(
token="YOUR_TOKEN",
)
client.tts.audio.speech(
- input="input",
- voice_id="voice_id",
+ audio_format="mp3",
+ input="Hello! This is the Speechify text-to-speech API.",
+ model="simba-english",
+ voice_id="george",
)
```
@@ -90,10 +94,7 @@ Please refer to the list of the supported languages and recommendations regardin
-
-**model:** `typing.Optional[GetSpeechRequestModel]`
-
-Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated.
-`simba-3.0` is the new streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships.
+**model:** `typing.Optional[GetSpeechRequestModel]` — Model used for audio synthesis. `simba-english` is optimized for English, `simba-multilingual` for non-English or mixed input. `simba-3.0` is the streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships.
@@ -133,7 +134,10 @@ Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated.
-
-Gets the stream speech for the given input
+Synthesize speech and stream the audio back as it is generated, for
+low-latency playback. The Accept header selects the audio container.
+For short text where receiving the whole file at once is fine, use
+POST /v1/audio/speech.
@@ -212,10 +216,7 @@ Please refer to the list of the supported languages and recommendations regardin
-
-**model:** `typing.Optional[GetStreamRequestModel]`
-
-Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated.
-`simba-3.0` is the new streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships.
+**model:** `typing.Optional[GetStreamRequestModel]` — Model used for audio synthesis. `simba-english` is optimized for English, `simba-multilingual` for non-English or mixed input. `simba-3.0` is the streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships.
@@ -239,88 +240,6 @@ Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated.
-
-
-
-
-## Tts Auth
-client.tts.auth.create_access_token(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-WARNING: This endpoint is deprecated. Create a new API token for the logged in user.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.auth.create_access_token(
- grant_type="client_credentials",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**grant_type:** `CreateAccessTokenRequestGrantType` — in: body
-
-
-
-
-
--
-
-**scope:** `typing.Optional[CreateAccessTokenRequestScope]`
-
-The scope, or a space-delimited list of scopes the token is requested for
-in: body
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
@@ -651,6758 +570,3 @@ client.tts.voices.download_sample(
-## Tts Agents
-client.tts.agents.list()
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List voice agents owned by the caller.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.list()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.create(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Create a voice agent.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.create(
- name="name",
- voice_id="voice_id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**name:** `str`
-
-
-
-
-
--
-
-**voice_id:** `str` — Voice slug from the VMS catalog (see GET /v1/voices). Required — the server rejects writes with an unknown or empty slug.
-
-
-
-
-
--
-
-**slug:** `typing.Optional[str]` — Optional. Server derives slug from name with a random suffix when omitted; if you supply your own, a collision returns 400 'slug already taken'.
-
-
-
-
-
--
-
-**prompt:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**first_message:** `typing.Optional[str]` — Spoken verbatim at session start — no LLM round trip.
-
-
-
-
-
--
-
-**language:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**llm_model:** `typing.Optional[str]` — Optional chat model slug. Leave empty to use the Speechify default.
-
-
-
-
-
--
-
-**temperature:** `typing.Optional[float]`
-
-
-
-
-
--
-
-**config:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]`
-
-
-
-
-
--
-
-**is_public:** `typing.Optional[bool]`
-
-
-
-
-
--
-
-**allowed_origins:** `typing.Optional[typing.Sequence[str]]`
-
-
-
-
-
--
-
-**hostname_allowlist:** `typing.Optional[typing.Sequence[str]]` — Optional per-agent hostname allowlist (see Agent schema).
-
-
-
-
-
--
-
-**memory_enabled:** `typing.Optional[bool]`
-
-
-
-
-
--
-
-**memory_retention_days:** `typing.Optional[int]`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.get(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Retrieve a voice agent by ID.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.get(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.delete(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Delete a voice agent. Conversations and attached tools remain.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.delete(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.update(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Update a voice agent. Only fields present on the request body are changed.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.update(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**name:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**prompt:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**first_message:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**language:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**llm_model:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**voice_id:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**temperature:** `typing.Optional[float]`
-
-
-
-
-
--
-
-**config:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]`
-
-
-
-
-
--
-
-**is_public:** `typing.Optional[bool]`
-
-
-
-
-
--
-
-**allowed_origins:** `typing.Optional[typing.Sequence[str]]`
-
-
-
-
-
--
-
-**hostname_allowlist:** `typing.Optional[typing.Sequence[str]]`
-
-When supplied, replaces the stored list. Pass an empty
-array to clear enforcement (public agent is open again).
-Omit the field to leave the existing value unchanged.
-
-
-
-
-
--
-
-**memory_enabled:** `typing.Optional[bool]`
-
-
-
-
-
--
-
-**memory_retention_days:** `typing.Optional[int]`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.list_tools(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List tools currently attached to the agent.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.list_tools(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.attach_tool(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Attach an existing tool to the agent so the LLM can call it.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.attach_tool(
- id="id",
- tool_id="toolId",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**tool_id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.detach_tool(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Detach a tool from the agent.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.detach_tool(
- id="id",
- tool_id="toolId",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**tool_id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.get_evaluation_config(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Retrieve the agent's post-call evaluation criteria + data-collection config.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.get_evaluation_config(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.update_evaluation_config(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Replace the agent's evaluation criteria + data-collection fields.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-from speechify.tts import DataCollectionField, EvaluationCriterion
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.update_evaluation_config(
- id="id",
- criteria=[
- EvaluationCriterion(
- id="id",
- name="name",
- description="description",
- )
- ],
- data_collection=[
- DataCollectionField(
- key="key",
- description="description",
- type="string",
- )
- ],
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**criteria:** `typing.Sequence[EvaluationCriterion]`
-
-
-
-
-
--
-
-**data_collection:** `typing.Sequence[DataCollectionField]`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.get_dynamic_variables(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Retrieve the agent's customer-scope dynamic variables and the read-only
-catalogue of reserved `system__*` keys. The system variables list is
-provided so editor UIs can render the reference list without maintaining
-a client-side copy of the catalogue.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.get_dynamic_variables(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.update_dynamic_variables(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Replace the agent's customer-scope dynamic variable definitions.
-The supplied list overwrites the stored list wholesale (same
-semantics as `updateEvaluationConfig`). Pass an empty array to
-clear all variables. Up to 20 variables per agent. Keys must
-match `[a-zA-Z0-9_]+` and must not start with the reserved
-`system__` prefix.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-from speechify.tts import DynamicVariable
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.update_dynamic_variables(
- id="id",
- variables=[
- DynamicVariable(
- key="product_name",
- type="string",
- default="Speechify",
- description="Product the agent is supporting.",
- ),
- DynamicVariable(
- key="support_tier",
- type="number",
- default=1,
- ),
- DynamicVariable(
- key="account_metadata",
- type="json",
- description="Arbitrary account context injected into tool bodies.",
- ),
- ],
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**variables:** `typing.Sequence[DynamicVariable]` — The new variable list. Replaces the existing list entirely.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.create_conversation(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Start a new voice conversation with the agent. Returns a realtime
-voice session + short-lived client token so the caller can
-connect the audio pipeline directly. The agent is dispatched
-server-side; no additional client action required.
-
-Pass `dynamic_variables` to supply per-session values that override
-the agent's stored variable defaults for this one conversation.
-Keys in the `system__` namespace are rejected at this boundary.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.create_conversation(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**transport:** `typing.Optional[str]` — Transport hint. Omit to use the agent's default.
-
-
-
-
-
--
-
-**dynamic_variables:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]`
-
-Per-session variable overrides that merge on top of the agent's
-stored variable defaults for this one conversation. Keys in the
-reserved `system__` namespace are rejected. Values must match the
-declared type of the corresponding variable definition on the agent.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.create_session(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Mint a realtime voice session for the given agent. Widget-friendly
-counterpart to `createConversation` — same response shape, dual
-authentication:
-
-* **Authenticated (Bearer)**: works for any agent the caller
- owns. Typical server-to-server flow where the embedding
- site's backend mints a token and hands it to the browser so
- the API key never reaches the client.
-* **Unauthenticated**: works only when `agent.is_public = true`
- AND the request's `Origin` header matches `agent.allowed_origins`
- (or that list is empty). When `agent.hostname_allowlist` is
- non-empty, the `Origin` hostname must additionally be a
- member of that list. Used directly by the
- `` web component.
-
-Responds with the same `CreateConversationResponse` as
-`createConversation`.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.create_session(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**user_identity:** `typing.Optional[str]` — Opaque identifier for the end-user (e.g. your app's user ID). Stamped onto the conversation. Optional - defaults to an anonymous per-session ID.
-
-
-
-
-
--
-
-**dynamic_variables:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]`
-
-Per-session variable overrides that merge on top of the agent's
-stored variable defaults for this one session. Keys in the
-reserved `system__` namespace are rejected at this boundary.
-Values must match the declared type of the corresponding variable
-definition on the agent (a `string` type expects a JSON string,
-`number` expects a JSON number, etc.).
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.list_agent_knowledge_bases(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List knowledge bases attached to an agent.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.list_agent_knowledge_bases(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.attach_knowledge_base(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Attach a knowledge base to an agent. The `search_knowledge` tool
-is auto-registered on the next conversation and can only query the
-attached knowledge bases.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.attach_knowledge_base(
- id="id",
- kb_id="kbId",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**kb_id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.detach_knowledge_base(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Detach a knowledge base from an agent.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.detach_knowledge_base(
- id="id",
- kb_id="kbId",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**kb_id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.list_memories(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List per-caller memories extracted for an agent. Memories are
-written post-call by the built-in extractor when `memory_enabled`
-is true on the agent; the list is sorted newest-first.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.list_memories(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**limit:** `typing.Optional[int]` — Maximum rows to return. Defaults to 100, capped at 200.
-
-
-
-
-
--
-
-**offset:** `typing.Optional[int]` — Number of rows to skip. Combine with `limit` to page through older memories.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.delete_memories_by_caller(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Delete every memory ever extracted for a specific caller on
-this agent. Privacy / GDPR surface. Returns the count of rows
-soft-deleted; rows become permanently unreachable immediately
-and are hard-deleted by the retention job after the tenant's
-configured retention window.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.delete_memories_by_caller(
- id="id",
- agent_id="agent_id",
- caller_identity="caller_identity",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**agent_id:** `str`
-
-
-
-
-
--
-
-**caller_identity:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.list_tests(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List all tests configured for the agent. Each entry includes the
-most recent run so the console can render pass/fail badges without
-an extra round-trip.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.list_tests(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str` — Agent ID.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.create_test(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Create a new test for the agent.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-from speechify.tts import ScenarioConfig
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.create_test(
- id="id",
- name="Greet the caller by name",
- description="Agent should greet the caller using their name when provided.",
- type="scenario",
- config=ScenarioConfig(
- context="The caller says: Hi, I'm Alice.",
- success_criteria="The agent greets Alice by name.",
- success_examples=["Hi Alice! How can I help you today?"],
- failure_examples=["Hello! How can I help you?"],
- ),
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str` — Agent ID.
-
-
-
-
-
--
-
-**name:** `str` — Short human-readable label for the test.
-
-
-
-
-
--
-
-**type:** `TestType`
-
-
-
-
-
--
-
-**config:** `CreateAgentTestRequestConfig` — Type-specific configuration. Must match the shape for the given `type`.
-
-
-
-
-
--
-
-**description:** `typing.Optional[str]` — Optional longer description of what this test verifies.
-
-
-
-
-
--
-
-**tool_mock_config:** `typing.Optional[ToolMockConfig]` — Optional tool-mocking config applied during every run of this test.
-
-
-
-
-
--
-
-**variables:** `typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]`
-
-Per-test variable values substituted into string fields of the
-config at run-start. Keys use the same rules as agent-level
-`DynamicVariable` keys.
-
-
-
-
-
--
-
-**folder_id:** `typing.Optional[str]` — Folder to place the test in. Omit for root.
-
-
-
-
-
--
-
-**attached_agent_ids:** `typing.Optional[typing.Sequence[str]]`
-
-Optional list of additional agents this test should also run
-against. The owner agent (path param) is always attached
-implicitly.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.run_all_tests(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Enqueue runs for every test on the agent concurrently. Up to 50
-tests are dispatched in one call. Each returned run starts in
-`queued` status; poll `GET /v1/test-runs/{id}` for the terminal
-result.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.run_all_tests(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str` — Agent ID.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.get_test(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Retrieve a test by ID.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.get_test(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str` — Test ID.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.delete_test(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Delete a test and all its run history.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.delete_test(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str` — Test ID.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.update_test(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Update a test. Only fields present on the request body are changed.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.update_test(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str` — Test ID.
-
-
-
-
-
--
-
-**name:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**description:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**config:** `typing.Optional[UpdateAgentTestRequestConfig]` — Replaces the test config when present.
-
-
-
-
-
--
-
-**tool_mock_config:** `typing.Optional[ToolMockConfig]` — Replaces the tool-mock config when present.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.list_test_runs(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List the run history for a test, newest first.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.list_test_runs(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str` — Test ID.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.run_test(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Enqueue a single run of the test. The returned run starts in
-`queued` status. Poll `GET /v1/test-runs/{id}` until the status
-reaches a terminal state (`passed`, `failed`, or `error`).
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.run_test(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str` — Test ID.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.get_test_run(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Retrieve a single test run by ID. Poll this endpoint until
-`status` reaches a terminal state (`passed`, `failed`, or `error`).
-The `result` field is populated on terminal states.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.get_test_run(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str` — Test run ID.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.list_all_tests(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Workspace-wide list of tests across every agent the caller owns.
-Supports filters (agent, type, last-run status, folder), full-text
-search on name/description, and cursor pagination. Each row carries
-its newest run and attached agent IDs so the list renders without
-N+1 round-trips.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.list_all_tests()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**agent_id:** `typing.Optional[str]` — Comma-separated agent IDs to filter on.
-
-
-
-
-
--
-
-**type:** `typing.Optional[str]` — Comma-separated test types (scenario|tool|simulation).
-
-
-
-
-
--
-
-**status:** `typing.Optional[str]` — Comma-separated last-run statuses.
-
-
-
-
-
--
-
-**folder_id:** `typing.Optional[str]` — Folder ID to filter on, or "root" for unfiled tests.
-
-
-
-
-
--
-
-**updated_after:** `typing.Optional[str]` — Only return tests updated after this RFC3339 timestamp.
-
-
-
-
-
--
-
-**q:** `typing.Optional[str]` — Substring match on name or description.
-
-
-
-
-
--
-
-**limit:** `typing.Optional[int]` — Max tests per page (default 50, max 200).
-
-
-
-
-
--
-
-**cursor:** `typing.Optional[str]` — Opaque pagination cursor from a previous response.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.get_test_stats(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Aggregate pass-rate metrics over the last N days. Returns dense
-daily buckets (one entry per day, zero-filled) plus totals and a
-per-type breakdown. Powers the header chart on the global tests
-page. Default window is 30 days, max 90.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.get_test_stats()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**window_days:** `typing.Optional[int]` — Trailing window in days (default 30, max 90).
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.run_tests_batch(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Queue runs for every (test, agent) pair in the body. Entries
-without an `agent_id` fan out to every agent the test is
-attached to. Total expanded runs are capped at 100 per call.
-Each entry in the response is a queued run; poll
-`GET /v1/test-runs/{id}` for each.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-from speechify.tts import BatchRunEntry
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.run_tests_batch(
- entries=[
- BatchRunEntry(
- test_id="test_id",
- )
- ],
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**entries:** `typing.Sequence[BatchRunEntry]`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.list_test_attachments(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List every agent a test is attached to.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.list_test_attachments(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.attach_test(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Attach a test to an additional agent. After this call, the test
-will also run as part of that agent's regression suite (and
-against its prompt + tool config when invoked with
-`agent_id = {agentId}`). Idempotent.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.attach_test(
- id="id",
- agent_id="agentId",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**agent_id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.detach_test(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Detach a test from an agent. The owner agent (the agent the test
-was authored against) cannot be detached; delete the test
-instead.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.detach_test(
- id="id",
- agent_id="agentId",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**agent_id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.move_test(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Move a test into a folder. Pass `folder_id: null` for root.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.move_test(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**folder_id:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.list_test_folders()
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List every test folder the caller owns. Flat list; build the tree client-side.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.list_test_folders()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.create_test_folder(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Create a test folder. Max depth is 3.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.create_test_folder(
- name="name",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**name:** `str`
-
-
-
-
-
--
-
-**parent_folder_id:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.delete_test_folder(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Soft-delete a folder. Child tests drop back to root.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.delete_test_folder(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.agents.update_test_folder(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Rename or reparent a test folder. Cycles are rejected.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.agents.update_test_folder(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**name:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**parent_folder_id:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-## Tts Tools
-client.tts.tools.list()
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List tools owned by the caller.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.tools.list()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.tools.create(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Create a tool. For webhook tools, the response includes the HMAC
-`webhook_secret` exactly once — store it immediately; subsequent
-reads return a masked placeholder.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-from speechify.tts import SystemToolConfig
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.tools.create(
- name="name",
- description="description",
- kind="system",
- config=SystemToolConfig(
- builtin="end_call",
- ),
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**name:** `str`
-
-
-
-
-
--
-
-**description:** `str`
-
-
-
-
-
--
-
-**kind:** `ToolKind`
-
-
-
-
-
--
-
-**config:** `CreateToolRequestConfig`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.tools.get(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Retrieve a tool by ID. Webhook secrets are always masked here.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.tools.get(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.tools.delete(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Delete a tool. Agents that had it attached get a soft-detach.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.tools.delete(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.tools.update(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Update a tool. Tool kind is immutable — create a new tool to change it.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.tools.update(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**name:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**description:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**config:** `typing.Optional[UpdateToolRequestConfig]`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-## Tts Conversations
-client.tts.conversations.list()
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List conversations owned by the caller, ordered by most recent.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.conversations.list()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.conversations.stats()
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Aggregated counts and averages over the caller's conversations, scoped by the same filters as the list endpoint.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.conversations.stats()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.conversations.get(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Retrieve a conversation by ID.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.conversations.get(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.conversations.list_messages(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Retrieve the full transcript for a conversation, in order.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.conversations.list_messages(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.conversations.list_evaluations(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Retrieve post-call evaluation results for a conversation.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.conversations.list_evaluations(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.conversations.list_memories(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List memories extracted from a specific conversation.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.conversations.list_memories(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-## Tts KnowledgeBases
-client.tts.knowledge_bases.list()
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List knowledge bases owned by the caller.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.knowledge_bases.list()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.knowledge_bases.create(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Create a new knowledge base.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.knowledge_bases.create(
- name="name",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**name:** `str` — Human-readable label.
-
-
-
-
-
--
-
-**description:** `typing.Optional[str]` — Optional description.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.knowledge_bases.get(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Retrieve a knowledge base by ID.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.knowledge_bases.get(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.knowledge_bases.delete(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Soft-delete a knowledge base. Documents and chunks are cascaded.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.knowledge_bases.delete(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.knowledge_bases.update(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Update a knowledge base.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.knowledge_bases.update(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**name:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**description:** `typing.Optional[str]`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.knowledge_bases.list_documents(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List documents ingested into a knowledge base.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.knowledge_bases.list_documents(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.knowledge_bases.upload_document(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Upload a document (PDF, plain text, markdown, or HTML) to a
-knowledge base. The document is extracted, chunked, embedded, and
-indexed synchronously; expect a few seconds per MB of input.
-Maximum 10 MB per upload.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.knowledge_bases.upload_document(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**file:** `from __future__ import annotations
-
-core.File` — See core.File for more documentation
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.knowledge_bases.get_document(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Retrieve a document by ID.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.knowledge_bases.get_document(
- doc_id="docId",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**doc_id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.knowledge_bases.delete_document(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Delete a document and all its chunks.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.knowledge_bases.delete_document(
- doc_id="docId",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**doc_id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.knowledge_bases.list_chunks(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List the chunks for a document.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.knowledge_bases.list_chunks(
- doc_id="docId",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**doc_id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.knowledge_bases.search(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Semantic search across a caller-owned list of knowledge bases.
-Returns ranked chunks with source filename and a cosine-similarity
-score. Limited to 50 results per request.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.knowledge_bases.search(
- query="query",
- kb_ids=["kb_ids"],
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**query:** `str` — Natural-language search query.
-
-
-
-
-
--
-
-**kb_ids:** `typing.Sequence[str]` — Knowledge bases to search across. Results scoped to caller-owned entries; unknown IDs are silently ignored.
-
-
-
-
-
--
-
-**top_k:** `typing.Optional[int]` — Max hits to return (default 5, capped at 50).
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-## Tts Memories
-client.tts.memories.delete(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Soft-delete one memory row.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.memories.delete(
- memory_id="memoryId",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**memory_id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-## Tts PhoneNumbers
-client.tts.phone_numbers.list()
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List all phone numbers in the caller's workspace.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.phone_numbers.list()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.phone_numbers.import_(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Import a phone number into the workspace. The `source` field
-determines the provisioning path:
-
-- `livekit` - LiveKit purchases the number on your behalf. US
- inbound only. Quickest path for local testing.
-- `twilio` - Provide your Twilio Account SID, Auth Token, and
- the E.164 number you already own. We provision an Elastic SIP
- Trunk on your Twilio account automatically.
-- `byoc` - Provide an existing SIP trunk ID. The number is
- registered against that trunk.
-
-Returns 402 when the workspace has reached the 100-number cap.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.phone_numbers.import_(
- request={"key": "value"},
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request:** `typing.Optional[typing.Any]`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.phone_numbers.get(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Retrieve a phone number by ID.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.phone_numbers.get(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.phone_numbers.delete(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Delete a phone number from the workspace. For Twilio and LiveKit
-numbers this also deprovisions the backing SIP trunk and dispatch
-rule on LiveKit Cloud.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.phone_numbers.delete(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.phone_numbers.update(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Update a phone number. Only `label` and `agent_id` are mutable;
-`source` and `e164` are immutable after import. Pass `null` for
-`agent_id` to unbind the number from its current agent.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.phone_numbers.update(
- id="id",
- request={"key": "value"},
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request:** `typing.Optional[typing.Any]`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-## Tts SipTrunks
-client.tts.sip_trunks.list()
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List all SIP trunks in the caller's workspace.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.sip_trunks.list()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.sip_trunks.create(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Create a SIP trunk. For `kind=byoc` supply `sip_address` plus
-optional digest credentials and IP allowlist. For `kind=twilio`
-use `ImportPhoneNumber` with a `twilio` spec instead - trunk
-creation is handled automatically. Returns 402 when the workspace
-has reached the 20-trunk cap.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.sip_trunks.create(
- request={"key": "value"},
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request:** `typing.Optional[typing.Any]`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.sip_trunks.get(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Retrieve a SIP trunk by ID.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.sip_trunks.get(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.sip_trunks.delete(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Delete a SIP trunk. This also removes the backing LiveKit inbound
-trunk, outbound trunk, and dispatch rule if they were provisioned
-by us. Phone numbers attached to this trunk are left in place but
-become non-functional until rebound to a new trunk.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.sip_trunks.delete(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-## Tts OutboundCalls
-client.tts.outbound_calls.create(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Place an outbound call from an agent to a phone number. LiveKit
-originates the SIP INVITE through the outbound trunk bound to the
-agent's workspace; the agent worker is dispatched into the room
-automatically.
-
-The response is returned as soon as LiveKit accepts the INVITE.
-Poll `GET /v1/conversations/{conversation_id}` for status
-transitions: `pending` → `active` (answered) → `completed`.
-
-Requires a Twilio or BYOC trunk. LiveKit-native numbers are
-inbound-only.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.outbound_calls.create(
- request={"key": "value"},
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request:** `typing.Optional[typing.Any]`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-## Tts Workspaces
-client.tts.workspaces.list()
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List every workspace the authenticated user belongs to. Powers the workspace switcher.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.workspaces.list()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.workspaces.create(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Create a new workspace with the authenticated user as owner.
-The caller must switch their active workspace client-side via
-the `X-Tenant-ID` header to act on the new tenant.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.workspaces.create()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**name:** `typing.Optional[str]` — Display name for the new workspace. Trimmed; must be 120 characters or fewer.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.workspaces.get_current()
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Retrieve the workspace currently selected by the caller (via `X-Tenant-ID` or auto-resolved).
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.workspaces.get_current()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.workspaces.update_current(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Rename the current workspace. Owner or admin only.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.workspaces.update_current(
- name="name",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**name:** `str` — New display name. Required; must be 120 characters or fewer.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.workspaces.list_members()
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List every member of the current workspace. Any member may call this.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.workspaces.list_members()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.workspaces.leave()
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Remove the authenticated caller from the current workspace.
-Refused with 409 when the caller is the last owner — promote
-another member to owner first.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.workspaces.leave()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.workspaces.remove_member(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Remove a member from the current workspace. Owner or admin
-only. The caller cannot remove themselves — use
-`POST /v1/tenants/current/members/leave` instead.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.workspaces.remove_member(
- user_uid="user_uid",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**user_uid:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.workspaces.update_member_role(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Change a member's role. Owner only — admins may add or remove
-members but may not change roles. Refused with 409 when
-demoting the last remaining owner.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.workspaces.update_member_role(
- user_uid="user_uid",
- role="owner",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**user_uid:** `str`
-
-
-
-
-
--
-
-**role:** `MemberRole`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.workspaces.list_invites()
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-List outstanding invites for the current workspace. Invite tokens are redacted.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.workspaces.list_invites()
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.workspaces.create_invite(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Create an invite to the current workspace. Owner or admin only.
-The response contains the invite token ONCE — subsequent list
-calls redact it.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.workspaces.create_invite(
- email="email",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**email:** `str` — Email of the person to invite. Validated as an RFC 5322 address.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.workspaces.revoke_invite(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Revoke an outstanding invite. Owner or admin only. Idempotent.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.workspaces.revoke_invite(
- id="id",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**id:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.workspaces.accept_invite(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Accept a workspace invite. The authenticated caller is joined
-to the invite's workspace as a member. Expired, revoked, or
-already-accepted tokens return 404 to avoid token enumeration.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.workspaces.accept_invite(
- token="token",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**token:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.workspaces.preview_invite(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Preview a workspace invite without authenticating. Returns the
-workspace name, inviter details, and expiry so the `/join/{token}`
-page can render before the recipient signs in. Anyone with the
-token can already accept, so this endpoint deliberately surfaces
-the same information a caller would see after accepting. Invalid
-tokens (unknown, expired, revoked, already-accepted, or pointing
-at a soft-deleted workspace) collapse to a single 404 to prevent
-enumeration.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.workspaces.preview_invite(
- token="token",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**token:** `str`
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
-client.tts.workspaces.transfer_workspace_owner(...)
-
--
-
-#### 📝 Description
-
-
--
-
-
--
-
-Transfer ownership of the current workspace atomically. Promotes
-the target member to owner and demotes the caller to admin in a
-single transaction. Owner-only; admins cannot hand off a role
-they were never granted. Prefer this over two PATCH calls to
-`/v1/tenants/current/members/{user_uid}`: a sole-owner caller
-cannot demote themselves first without tripping the last-owner
-guard, which this endpoint sidesteps by promoting before
-demoting.
-
-
-
-
-
-#### 🔌 Usage
-
-
--
-
-
--
-
-```python
-from speechify import Speechify
-
-client = Speechify(
- token="YOUR_TOKEN",
-)
-client.tts.workspaces.transfer_workspace_owner(
- user_uid="user_uid",
-)
-
-```
-
-
-
-
-
-#### ⚙️ Parameters
-
-
--
-
-
--
-
-**user_uid:** `str` — Firebase UID of the member who will become the new owner.
-
-
-
-
-
--
-
-**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/speechify/__init__.py b/src/speechify/__init__.py
index c35fd6b..4c530dd 100644
--- a/src/speechify/__init__.py
+++ b/src/speechify/__init__.py
@@ -1,8 +1,80 @@
# This file was auto-generated by Fern from our API Definition.
+from .types import (
+ CreateVoiceLanguage,
+ CreateVoiceModel,
+ CreateVoiceModelName,
+ CreatedVoice,
+ CreatedVoiceGender,
+ CreatedVoiceType,
+ Error,
+ ErrorCode,
+ ErrorDetail,
+ GetSpeechOptionsRequest,
+ GetSpeechResponse,
+ GetSpeechResponseAudioFormat,
+ GetStreamOptionsRequest,
+ GetVoice,
+ GetVoiceGender,
+ GetVoiceLanguage,
+ GetVoiceType,
+ GetVoicesModel,
+ GetVoicesModelName,
+ NestedChunk,
+ SpeechMarks,
+)
+from .errors import (
+ BadGatewayError,
+ BadRequestError,
+ ForbiddenError,
+ InternalServerError,
+ NotFoundError,
+ PaymentRequiredError,
+ ServiceUnavailableError,
+ TooManyRequestsError,
+ UnauthorizedError,
+ UnprocessableEntityError,
+)
from . import tts
from .client import AsyncSpeechify, Speechify
from .environment import SpeechifyEnvironment
from .version import __version__
-__all__ = ["AsyncSpeechify", "Speechify", "SpeechifyEnvironment", "__version__", "tts"]
+__all__ = [
+ "AsyncSpeechify",
+ "BadGatewayError",
+ "BadRequestError",
+ "CreateVoiceLanguage",
+ "CreateVoiceModel",
+ "CreateVoiceModelName",
+ "CreatedVoice",
+ "CreatedVoiceGender",
+ "CreatedVoiceType",
+ "Error",
+ "ErrorCode",
+ "ErrorDetail",
+ "ForbiddenError",
+ "GetSpeechOptionsRequest",
+ "GetSpeechResponse",
+ "GetSpeechResponseAudioFormat",
+ "GetStreamOptionsRequest",
+ "GetVoice",
+ "GetVoiceGender",
+ "GetVoiceLanguage",
+ "GetVoiceType",
+ "GetVoicesModel",
+ "GetVoicesModelName",
+ "InternalServerError",
+ "NestedChunk",
+ "NotFoundError",
+ "PaymentRequiredError",
+ "ServiceUnavailableError",
+ "SpeechMarks",
+ "Speechify",
+ "SpeechifyEnvironment",
+ "TooManyRequestsError",
+ "UnauthorizedError",
+ "UnprocessableEntityError",
+ "__version__",
+ "tts",
+]
diff --git a/src/speechify/client.py b/src/speechify/client.py
index 909afb0..e356bae 100644
--- a/src/speechify/client.py
+++ b/src/speechify/client.py
@@ -4,6 +4,7 @@
from .environment import SpeechifyEnvironment
import os
import httpx
+from .core.api_error import ApiError
from .core.client_wrapper import SyncClientWrapper
from .tts.client import TtsClient
from .core.client_wrapper import AsyncClientWrapper
@@ -58,6 +59,10 @@ def __init__(
httpx_client: typing.Optional[httpx.Client] = None,
):
_defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None
+ if token is None:
+ raise ApiError(
+ body="The client must be instantiated be either passing in token or setting SPEECHIFY_API_KEY"
+ )
self._client_wrapper = SyncClientWrapper(
base_url=_get_base_url(base_url=base_url, environment=environment),
token=token,
@@ -119,6 +124,10 @@ def __init__(
httpx_client: typing.Optional[httpx.AsyncClient] = None,
):
_defaulted_timeout = timeout if timeout is not None else 60 if httpx_client is None else None
+ if token is None:
+ raise ApiError(
+ body="The client must be instantiated be either passing in token or setting SPEECHIFY_API_KEY"
+ )
self._client_wrapper = AsyncClientWrapper(
base_url=_get_base_url(base_url=base_url, environment=environment),
token=token,
diff --git a/src/speechify/tts/errors/__init__.py b/src/speechify/errors/__init__.py
similarity index 60%
rename from src/speechify/tts/errors/__init__.py
rename to src/speechify/errors/__init__.py
index 4bf158a..7b4bd00 100644
--- a/src/speechify/tts/errors/__init__.py
+++ b/src/speechify/errors/__init__.py
@@ -1,21 +1,25 @@
# This file was auto-generated by Fern from our API Definition.
+from .bad_gateway_error import BadGatewayError
from .bad_request_error import BadRequestError
-from .conflict_error import ConflictError
-from .content_too_large_error import ContentTooLargeError
from .forbidden_error import ForbiddenError
from .internal_server_error import InternalServerError
from .not_found_error import NotFoundError
from .payment_required_error import PaymentRequiredError
+from .service_unavailable_error import ServiceUnavailableError
+from .too_many_requests_error import TooManyRequestsError
from .unauthorized_error import UnauthorizedError
+from .unprocessable_entity_error import UnprocessableEntityError
__all__ = [
+ "BadGatewayError",
"BadRequestError",
- "ConflictError",
- "ContentTooLargeError",
"ForbiddenError",
"InternalServerError",
"NotFoundError",
"PaymentRequiredError",
+ "ServiceUnavailableError",
+ "TooManyRequestsError",
"UnauthorizedError",
+ "UnprocessableEntityError",
]
diff --git a/src/speechify/errors/bad_gateway_error.py b/src/speechify/errors/bad_gateway_error.py
new file mode 100644
index 0000000..a75235c
--- /dev/null
+++ b/src/speechify/errors/bad_gateway_error.py
@@ -0,0 +1,9 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from ..core.api_error import ApiError
+from ..types.error import Error
+
+
+class BadGatewayError(ApiError):
+ def __init__(self, body: Error):
+ super().__init__(status_code=502, body=body)
diff --git a/src/speechify/tts/errors/bad_request_error.py b/src/speechify/errors/bad_request_error.py
similarity index 85%
rename from src/speechify/tts/errors/bad_request_error.py
rename to src/speechify/errors/bad_request_error.py
index 66ac1e3..9c13c61 100644
--- a/src/speechify/tts/errors/bad_request_error.py
+++ b/src/speechify/errors/bad_request_error.py
@@ -1,6 +1,6 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.api_error import ApiError
+from ..core.api_error import ApiError
import typing
diff --git a/src/speechify/tts/errors/forbidden_error.py b/src/speechify/errors/forbidden_error.py
similarity index 57%
rename from src/speechify/tts/errors/forbidden_error.py
rename to src/speechify/errors/forbidden_error.py
index cc295c8..6f2a04a 100644
--- a/src/speechify/tts/errors/forbidden_error.py
+++ b/src/speechify/errors/forbidden_error.py
@@ -1,9 +1,9 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.api_error import ApiError
-import typing
+from ..core.api_error import ApiError
+from ..types.error import Error
class ForbiddenError(ApiError):
- def __init__(self, body: typing.Optional[typing.Any]):
+ def __init__(self, body: Error):
super().__init__(status_code=403, body=body)
diff --git a/src/speechify/tts/errors/internal_server_error.py b/src/speechify/errors/internal_server_error.py
similarity index 58%
rename from src/speechify/tts/errors/internal_server_error.py
rename to src/speechify/errors/internal_server_error.py
index 2bd9889..c5dcb4a 100644
--- a/src/speechify/tts/errors/internal_server_error.py
+++ b/src/speechify/errors/internal_server_error.py
@@ -1,9 +1,9 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.api_error import ApiError
-import typing
+from ..core.api_error import ApiError
+from ..types.error import Error
class InternalServerError(ApiError):
- def __init__(self, body: typing.Optional[typing.Any]):
+ def __init__(self, body: Error):
super().__init__(status_code=500, body=body)
diff --git a/src/speechify/tts/errors/not_found_error.py b/src/speechify/errors/not_found_error.py
similarity index 85%
rename from src/speechify/tts/errors/not_found_error.py
rename to src/speechify/errors/not_found_error.py
index f5fb993..a1235b8 100644
--- a/src/speechify/tts/errors/not_found_error.py
+++ b/src/speechify/errors/not_found_error.py
@@ -1,6 +1,6 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.api_error import ApiError
+from ..core.api_error import ApiError
import typing
diff --git a/src/speechify/tts/errors/payment_required_error.py b/src/speechify/errors/payment_required_error.py
similarity index 58%
rename from src/speechify/tts/errors/payment_required_error.py
rename to src/speechify/errors/payment_required_error.py
index 3a82ecc..4159359 100644
--- a/src/speechify/tts/errors/payment_required_error.py
+++ b/src/speechify/errors/payment_required_error.py
@@ -1,9 +1,9 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.api_error import ApiError
-import typing
+from ..core.api_error import ApiError
+from ..types.error import Error
class PaymentRequiredError(ApiError):
- def __init__(self, body: typing.Optional[typing.Any]):
+ def __init__(self, body: Error):
super().__init__(status_code=402, body=body)
diff --git a/src/speechify/errors/service_unavailable_error.py b/src/speechify/errors/service_unavailable_error.py
new file mode 100644
index 0000000..81c32e6
--- /dev/null
+++ b/src/speechify/errors/service_unavailable_error.py
@@ -0,0 +1,9 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from ..core.api_error import ApiError
+from ..types.error import Error
+
+
+class ServiceUnavailableError(ApiError):
+ def __init__(self, body: Error):
+ super().__init__(status_code=503, body=body)
diff --git a/src/speechify/errors/too_many_requests_error.py b/src/speechify/errors/too_many_requests_error.py
new file mode 100644
index 0000000..c2b3b10
--- /dev/null
+++ b/src/speechify/errors/too_many_requests_error.py
@@ -0,0 +1,9 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from ..core.api_error import ApiError
+from ..types.error import Error
+
+
+class TooManyRequestsError(ApiError):
+ def __init__(self, body: Error):
+ super().__init__(status_code=429, body=body)
diff --git a/src/speechify/tts/errors/unauthorized_error.py b/src/speechify/errors/unauthorized_error.py
similarity index 85%
rename from src/speechify/tts/errors/unauthorized_error.py
rename to src/speechify/errors/unauthorized_error.py
index b8bb12b..1c00f98 100644
--- a/src/speechify/tts/errors/unauthorized_error.py
+++ b/src/speechify/errors/unauthorized_error.py
@@ -1,6 +1,6 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.api_error import ApiError
+from ..core.api_error import ApiError
import typing
diff --git a/src/speechify/errors/unprocessable_entity_error.py b/src/speechify/errors/unprocessable_entity_error.py
new file mode 100644
index 0000000..f9752ba
--- /dev/null
+++ b/src/speechify/errors/unprocessable_entity_error.py
@@ -0,0 +1,9 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from ..core.api_error import ApiError
+from ..types.error import Error
+
+
+class UnprocessableEntityError(ApiError):
+ def __init__(self, body: Error):
+ super().__init__(status_code=422, body=body)
diff --git a/src/speechify/tts/__init__.py b/src/speechify/tts/__init__.py
index 878b91d..2bdc653 100644
--- a/src/speechify/tts/__init__.py
+++ b/src/speechify/tts/__init__.py
@@ -1,297 +1,15 @@
# This file was auto-generated by Fern from our API Definition.
-from .types import (
- AccessToken,
- AccessTokenScope,
- AccessTokenTokenType,
- Agent,
- AgentTest,
- AgentTestAttachment,
- AgentTestConfig,
- AgentTestFolder,
- AgentTestRun,
- AgentTestWithLastRun,
- ApiKey,
- BatchRunEntry,
- ClientToolConfig,
- Conversation,
- ConversationStats,
- ConversationStatus,
- ConversationTransport,
- CreateConversationResponse,
- CreateVoiceLanguage,
- CreateVoiceModel,
- CreateVoiceModelName,
- CreatedVoice,
- CreatedVoiceGender,
- CreatedVoiceType,
- DataCollectionField,
- DataCollectionFieldType,
- DeleteMemoriesByCallerResponse,
- DynamicVariable,
- DynamicVariableType,
- Evaluation,
- EvaluationConfig,
- EvaluationCriterion,
- EvaluationKind,
- EvaluationStatus,
- GetSpeechOptionsRequest,
- GetSpeechResponse,
- GetSpeechResponseAudioFormat,
- GetStreamOptionsRequest,
- GetVoice,
- GetVoiceGender,
- GetVoiceLanguage,
- GetVoiceType,
- GetVoicesModel,
- GetVoicesModelName,
- Invite,
- InvitePreview,
- InvitesListResponse,
- KnowledgeBase,
- KnowledgeBaseChunk,
- KnowledgeBaseDocument,
- KnowledgeBaseDocumentStatus,
- KnowledgeBaseSearchHit,
- ListAgentTestAttachmentsResponse,
- ListAgentTestFoldersResponse,
- ListAgentTestRunsResponse,
- ListAgentTestsResponse,
- ListAgentsResponse,
- ListConversationsResponse,
- ListDynamicVariablesResponse,
- ListEvaluationsResponse,
- ListKnowledgeBaseChunksResponse,
- ListKnowledgeBaseDocumentsResponse,
- ListKnowledgeBasesResponse,
- ListMemoriesResponse,
- ListMessagesResponse,
- ListTestsResponse,
- ListToolsResponse,
- Member,
- MemberRole,
- MembersListResponse,
- Memory,
- Message,
- MessageRole,
- MockingStrategy,
- NestedChunk,
- NoMatchBehavior,
- OAuthError,
- OAuthErrorError,
- ParameterCheck,
- ParameterCheckMode,
- ParameterCheckResult,
- RunAgentTestsResponse,
- RunBatchResponse,
- ScenarioConfig,
- ScenarioResult,
- SearchKnowledgeBasesResponse,
- SimulationConfig,
- SimulationMessage,
- SimulationMessageRole,
- SimulationResult,
- SimulationToolCall,
- SpeechMarks,
- SystemToolConfig,
- SystemToolConfigBuiltin,
- SystemVariableDoc,
- Tenant,
- TenantDataRegion,
- TenantPlan,
- TenantsListResponse,
- TestRunResult,
- TestRunStatus,
- TestStats,
- TestStatsBucket,
- TestType,
- Tool,
- ToolCallConfig,
- ToolCallResult,
- ToolConfig,
- ToolKind,
- ToolMock,
- ToolMockConfig,
- ToolParam,
- ToolParamType,
- WebhookToolConfig,
- WebhookToolConfigMethod,
-)
-from .errors import (
- BadRequestError,
- ConflictError,
- ContentTooLargeError,
- ForbiddenError,
- InternalServerError,
- NotFoundError,
- PaymentRequiredError,
- UnauthorizedError,
-)
-from . import (
- agents,
- audio,
- auth,
- conversations,
- knowledge_bases,
- memories,
- outbound_calls,
- phone_numbers,
- sip_trunks,
- tools,
- voices,
- workspaces,
-)
-from .agents import CreateAgentTestRequestConfig, UpdateAgentTestRequestConfig
+from . import audio, voices
from .audio import GetSpeechRequestAudioFormat, GetSpeechRequestModel, GetStreamRequestModel, StreamAudioRequestAccept
-from .auth import CreateAccessTokenRequestGrantType, CreateAccessTokenRequestScope
-from .tools import CreateToolRequestConfig, UpdateToolRequestConfig
from .voices import CreateVoicesRequestGender
__all__ = [
- "AccessToken",
- "AccessTokenScope",
- "AccessTokenTokenType",
- "Agent",
- "AgentTest",
- "AgentTestAttachment",
- "AgentTestConfig",
- "AgentTestFolder",
- "AgentTestRun",
- "AgentTestWithLastRun",
- "ApiKey",
- "BadRequestError",
- "BatchRunEntry",
- "ClientToolConfig",
- "ConflictError",
- "ContentTooLargeError",
- "Conversation",
- "ConversationStats",
- "ConversationStatus",
- "ConversationTransport",
- "CreateAccessTokenRequestGrantType",
- "CreateAccessTokenRequestScope",
- "CreateAgentTestRequestConfig",
- "CreateConversationResponse",
- "CreateToolRequestConfig",
- "CreateVoiceLanguage",
- "CreateVoiceModel",
- "CreateVoiceModelName",
"CreateVoicesRequestGender",
- "CreatedVoice",
- "CreatedVoiceGender",
- "CreatedVoiceType",
- "DataCollectionField",
- "DataCollectionFieldType",
- "DeleteMemoriesByCallerResponse",
- "DynamicVariable",
- "DynamicVariableType",
- "Evaluation",
- "EvaluationConfig",
- "EvaluationCriterion",
- "EvaluationKind",
- "EvaluationStatus",
- "ForbiddenError",
- "GetSpeechOptionsRequest",
"GetSpeechRequestAudioFormat",
"GetSpeechRequestModel",
- "GetSpeechResponse",
- "GetSpeechResponseAudioFormat",
- "GetStreamOptionsRequest",
"GetStreamRequestModel",
- "GetVoice",
- "GetVoiceGender",
- "GetVoiceLanguage",
- "GetVoiceType",
- "GetVoicesModel",
- "GetVoicesModelName",
- "InternalServerError",
- "Invite",
- "InvitePreview",
- "InvitesListResponse",
- "KnowledgeBase",
- "KnowledgeBaseChunk",
- "KnowledgeBaseDocument",
- "KnowledgeBaseDocumentStatus",
- "KnowledgeBaseSearchHit",
- "ListAgentTestAttachmentsResponse",
- "ListAgentTestFoldersResponse",
- "ListAgentTestRunsResponse",
- "ListAgentTestsResponse",
- "ListAgentsResponse",
- "ListConversationsResponse",
- "ListDynamicVariablesResponse",
- "ListEvaluationsResponse",
- "ListKnowledgeBaseChunksResponse",
- "ListKnowledgeBaseDocumentsResponse",
- "ListKnowledgeBasesResponse",
- "ListMemoriesResponse",
- "ListMessagesResponse",
- "ListTestsResponse",
- "ListToolsResponse",
- "Member",
- "MemberRole",
- "MembersListResponse",
- "Memory",
- "Message",
- "MessageRole",
- "MockingStrategy",
- "NestedChunk",
- "NoMatchBehavior",
- "NotFoundError",
- "OAuthError",
- "OAuthErrorError",
- "ParameterCheck",
- "ParameterCheckMode",
- "ParameterCheckResult",
- "PaymentRequiredError",
- "RunAgentTestsResponse",
- "RunBatchResponse",
- "ScenarioConfig",
- "ScenarioResult",
- "SearchKnowledgeBasesResponse",
- "SimulationConfig",
- "SimulationMessage",
- "SimulationMessageRole",
- "SimulationResult",
- "SimulationToolCall",
- "SpeechMarks",
"StreamAudioRequestAccept",
- "SystemToolConfig",
- "SystemToolConfigBuiltin",
- "SystemVariableDoc",
- "Tenant",
- "TenantDataRegion",
- "TenantPlan",
- "TenantsListResponse",
- "TestRunResult",
- "TestRunStatus",
- "TestStats",
- "TestStatsBucket",
- "TestType",
- "Tool",
- "ToolCallConfig",
- "ToolCallResult",
- "ToolConfig",
- "ToolKind",
- "ToolMock",
- "ToolMockConfig",
- "ToolParam",
- "ToolParamType",
- "UnauthorizedError",
- "UpdateAgentTestRequestConfig",
- "UpdateToolRequestConfig",
- "WebhookToolConfig",
- "WebhookToolConfigMethod",
- "agents",
"audio",
- "auth",
- "conversations",
- "knowledge_bases",
- "memories",
- "outbound_calls",
- "phone_numbers",
- "sip_trunks",
- "tools",
"voices",
- "workspaces",
]
diff --git a/src/speechify/tts/agents/__init__.py b/src/speechify/tts/agents/__init__.py
deleted file mode 100644
index 1e56e81..0000000
--- a/src/speechify/tts/agents/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from .types import CreateAgentTestRequestConfig, UpdateAgentTestRequestConfig
-
-__all__ = ["CreateAgentTestRequestConfig", "UpdateAgentTestRequestConfig"]
diff --git a/src/speechify/tts/agents/client.py b/src/speechify/tts/agents/client.py
deleted file mode 100644
index 17433d1..0000000
--- a/src/speechify/tts/agents/client.py
+++ /dev/null
@@ -1,6604 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from ...core.client_wrapper import SyncClientWrapper
-from ...core.request_options import RequestOptions
-from ..types.list_agents_response import ListAgentsResponse
-from ...core.pydantic_utilities import parse_obj_as
-from ..errors.unauthorized_error import UnauthorizedError
-from json.decoder import JSONDecodeError
-from ...core.api_error import ApiError
-from ..types.agent import Agent
-from ..errors.bad_request_error import BadRequestError
-from ...core.jsonable_encoder import jsonable_encoder
-from ..errors.not_found_error import NotFoundError
-from ..types.list_tools_response import ListToolsResponse
-from ..types.evaluation_config import EvaluationConfig
-from ..types.evaluation_criterion import EvaluationCriterion
-from ..types.data_collection_field import DataCollectionField
-from ...core.serialization import convert_and_respect_annotation_metadata
-from ..types.list_dynamic_variables_response import ListDynamicVariablesResponse
-from ..types.dynamic_variable import DynamicVariable
-from ..types.create_conversation_response import CreateConversationResponse
-from ..errors.forbidden_error import ForbiddenError
-from ..types.list_knowledge_bases_response import ListKnowledgeBasesResponse
-from ..types.list_memories_response import ListMemoriesResponse
-from ..types.delete_memories_by_caller_response import DeleteMemoriesByCallerResponse
-from ..types.list_agent_tests_response import ListAgentTestsResponse
-from ..types.test_type import TestType
-from .types.create_agent_test_request_config import CreateAgentTestRequestConfig
-from ..types.tool_mock_config import ToolMockConfig
-from ..types.agent_test import AgentTest
-from ..types.run_agent_tests_response import RunAgentTestsResponse
-from .types.update_agent_test_request_config import UpdateAgentTestRequestConfig
-from ..types.list_agent_test_runs_response import ListAgentTestRunsResponse
-from ..types.agent_test_run import AgentTestRun
-from ..types.list_tests_response import ListTestsResponse
-from ..types.test_stats import TestStats
-from ..types.batch_run_entry import BatchRunEntry
-from ..types.run_batch_response import RunBatchResponse
-from ..types.list_agent_test_attachments_response import ListAgentTestAttachmentsResponse
-from ..types.list_agent_test_folders_response import ListAgentTestFoldersResponse
-from ..types.agent_test_folder import AgentTestFolder
-from ...core.client_wrapper import AsyncClientWrapper
-
-# this is used as the default value for optional parameters
-OMIT = typing.cast(typing.Any, ...)
-
-
-class AgentsClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListAgentsResponse:
- """
- List voice agents owned by the caller.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListAgentsResponse
- A list of voice agents.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.list()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/agents",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListAgentsResponse,
- parse_obj_as(
- type_=ListAgentsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def create(
- self,
- *,
- name: str,
- voice_id: str,
- slug: typing.Optional[str] = OMIT,
- prompt: typing.Optional[str] = OMIT,
- first_message: typing.Optional[str] = OMIT,
- language: typing.Optional[str] = OMIT,
- llm_model: typing.Optional[str] = OMIT,
- temperature: typing.Optional[float] = OMIT,
- config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
- is_public: typing.Optional[bool] = OMIT,
- allowed_origins: typing.Optional[typing.Sequence[str]] = OMIT,
- hostname_allowlist: typing.Optional[typing.Sequence[str]] = OMIT,
- memory_enabled: typing.Optional[bool] = OMIT,
- memory_retention_days: typing.Optional[int] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> Agent:
- """
- Create a voice agent.
-
- Parameters
- ----------
- name : str
-
- voice_id : str
- Voice slug from the VMS catalog (see GET /v1/voices). Required — the server rejects writes with an unknown or empty slug.
-
- slug : typing.Optional[str]
- Optional. Server derives slug from name with a random suffix when omitted; if you supply your own, a collision returns 400 'slug already taken'.
-
- prompt : typing.Optional[str]
-
- first_message : typing.Optional[str]
- Spoken verbatim at session start — no LLM round trip.
-
- language : typing.Optional[str]
-
- llm_model : typing.Optional[str]
- Optional chat model slug. Leave empty to use the Speechify default.
-
- temperature : typing.Optional[float]
-
- config : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
-
- is_public : typing.Optional[bool]
-
- allowed_origins : typing.Optional[typing.Sequence[str]]
-
- hostname_allowlist : typing.Optional[typing.Sequence[str]]
- Optional per-agent hostname allowlist (see Agent schema).
-
- memory_enabled : typing.Optional[bool]
-
- memory_retention_days : typing.Optional[int]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Agent
- The created agent.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.create(
- name="name",
- voice_id="voice_id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/agents",
- method="POST",
- json={
- "name": name,
- "slug": slug,
- "prompt": prompt,
- "first_message": first_message,
- "language": language,
- "llm_model": llm_model,
- "voice_id": voice_id,
- "temperature": temperature,
- "config": config,
- "is_public": is_public,
- "allowed_origins": allowed_origins,
- "hostname_allowlist": hostname_allowlist,
- "memory_enabled": memory_enabled,
- "memory_retention_days": memory_retention_days,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Agent,
- parse_obj_as(
- type_=Agent, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Agent:
- """
- Retrieve a voice agent by ID.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Agent
- The requested agent.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.get(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Agent,
- parse_obj_as(
- type_=Agent, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Delete a voice agent. Conversations and attached tools remain.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.delete(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def update(
- self,
- id: str,
- *,
- name: typing.Optional[str] = OMIT,
- prompt: typing.Optional[str] = OMIT,
- first_message: typing.Optional[str] = OMIT,
- language: typing.Optional[str] = OMIT,
- llm_model: typing.Optional[str] = OMIT,
- voice_id: typing.Optional[str] = OMIT,
- temperature: typing.Optional[float] = OMIT,
- config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
- is_public: typing.Optional[bool] = OMIT,
- allowed_origins: typing.Optional[typing.Sequence[str]] = OMIT,
- hostname_allowlist: typing.Optional[typing.Sequence[str]] = OMIT,
- memory_enabled: typing.Optional[bool] = OMIT,
- memory_retention_days: typing.Optional[int] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> Agent:
- """
- Update a voice agent. Only fields present on the request body are changed.
-
- Parameters
- ----------
- id : str
-
- name : typing.Optional[str]
-
- prompt : typing.Optional[str]
-
- first_message : typing.Optional[str]
-
- language : typing.Optional[str]
-
- llm_model : typing.Optional[str]
-
- voice_id : typing.Optional[str]
-
- temperature : typing.Optional[float]
-
- config : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
-
- is_public : typing.Optional[bool]
-
- allowed_origins : typing.Optional[typing.Sequence[str]]
-
- hostname_allowlist : typing.Optional[typing.Sequence[str]]
- When supplied, replaces the stored list. Pass an empty
- array to clear enforcement (public agent is open again).
- Omit the field to leave the existing value unchanged.
-
- memory_enabled : typing.Optional[bool]
-
- memory_retention_days : typing.Optional[int]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Agent
- The updated agent.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.update(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}",
- method="PATCH",
- json={
- "name": name,
- "prompt": prompt,
- "first_message": first_message,
- "language": language,
- "llm_model": llm_model,
- "voice_id": voice_id,
- "temperature": temperature,
- "config": config,
- "is_public": is_public,
- "allowed_origins": allowed_origins,
- "hostname_allowlist": hostname_allowlist,
- "memory_enabled": memory_enabled,
- "memory_retention_days": memory_retention_days,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Agent,
- parse_obj_as(
- type_=Agent, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_tools(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> ListToolsResponse:
- """
- List tools currently attached to the agent.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListToolsResponse
- Attached tools for the agent.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.list_tools(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/tools",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListToolsResponse,
- parse_obj_as(
- type_=ListToolsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def attach_tool(self, id: str, tool_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Attach an existing tool to the agent so the LLM can call it.
-
- Parameters
- ----------
- id : str
-
- tool_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.attach_tool(
- id="id",
- tool_id="toolId",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/tools/{jsonable_encoder(tool_id)}",
- method="POST",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def detach_tool(self, id: str, tool_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Detach a tool from the agent.
-
- Parameters
- ----------
- id : str
-
- tool_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.detach_tool(
- id="id",
- tool_id="toolId",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/tools/{jsonable_encoder(tool_id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def get_evaluation_config(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> EvaluationConfig:
- """
- Retrieve the agent's post-call evaluation criteria + data-collection config.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- EvaluationConfig
- The evaluation config for the agent.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.get_evaluation_config(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/evaluation-config",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- EvaluationConfig,
- parse_obj_as(
- type_=EvaluationConfig, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def update_evaluation_config(
- self,
- id: str,
- *,
- criteria: typing.Sequence[EvaluationCriterion],
- data_collection: typing.Sequence[DataCollectionField],
- request_options: typing.Optional[RequestOptions] = None,
- ) -> EvaluationConfig:
- """
- Replace the agent's evaluation criteria + data-collection fields.
-
- Parameters
- ----------
- id : str
-
- criteria : typing.Sequence[EvaluationCriterion]
-
- data_collection : typing.Sequence[DataCollectionField]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- EvaluationConfig
- The updated evaluation config.
-
- Examples
- --------
- from speechify import Speechify
- from speechify.tts import DataCollectionField, EvaluationCriterion
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.update_evaluation_config(
- id="id",
- criteria=[
- EvaluationCriterion(
- id="id",
- name="name",
- description="description",
- )
- ],
- data_collection=[
- DataCollectionField(
- key="key",
- description="description",
- type="string",
- )
- ],
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/evaluation-config",
- method="PATCH",
- json={
- "criteria": convert_and_respect_annotation_metadata(
- object_=criteria, annotation=typing.Sequence[EvaluationCriterion], direction="write"
- ),
- "data_collection": convert_and_respect_annotation_metadata(
- object_=data_collection, annotation=typing.Sequence[DataCollectionField], direction="write"
- ),
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- EvaluationConfig,
- parse_obj_as(
- type_=EvaluationConfig, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def get_dynamic_variables(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListDynamicVariablesResponse:
- """
- Retrieve the agent's customer-scope dynamic variables and the read-only
- catalogue of reserved `system__*` keys. The system variables list is
- provided so editor UIs can render the reference list without maintaining
- a client-side copy of the catalogue.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListDynamicVariablesResponse
- The agent's variable catalogue.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.get_dynamic_variables(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/variables",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListDynamicVariablesResponse,
- parse_obj_as(
- type_=ListDynamicVariablesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def update_dynamic_variables(
- self,
- id: str,
- *,
- variables: typing.Sequence[DynamicVariable],
- request_options: typing.Optional[RequestOptions] = None,
- ) -> ListDynamicVariablesResponse:
- """
- Replace the agent's customer-scope dynamic variable definitions.
- The supplied list overwrites the stored list wholesale (same
- semantics as `updateEvaluationConfig`). Pass an empty array to
- clear all variables. Up to 20 variables per agent. Keys must
- match `[a-zA-Z0-9_]+` and must not start with the reserved
- `system__` prefix.
-
- Parameters
- ----------
- id : str
-
- variables : typing.Sequence[DynamicVariable]
- The new variable list. Replaces the existing list entirely.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListDynamicVariablesResponse
- The updated variable catalogue.
-
- Examples
- --------
- from speechify import Speechify
- from speechify.tts import DynamicVariable
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.update_dynamic_variables(
- id="id",
- variables=[
- DynamicVariable(
- key="product_name",
- type="string",
- default="Speechify",
- description="Product the agent is supporting.",
- ),
- DynamicVariable(
- key="support_tier",
- type="number",
- default=1,
- ),
- DynamicVariable(
- key="account_metadata",
- type="json",
- description="Arbitrary account context injected into tool bodies.",
- ),
- ],
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/variables",
- method="PATCH",
- json={
- "variables": convert_and_respect_annotation_metadata(
- object_=variables, annotation=typing.Sequence[DynamicVariable], direction="write"
- ),
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListDynamicVariablesResponse,
- parse_obj_as(
- type_=ListDynamicVariablesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def create_conversation(
- self,
- id: str,
- *,
- transport: typing.Optional[str] = OMIT,
- dynamic_variables: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> CreateConversationResponse:
- """
- Start a new voice conversation with the agent. Returns a realtime
- voice session + short-lived client token so the caller can
- connect the audio pipeline directly. The agent is dispatched
- server-side; no additional client action required.
-
- Pass `dynamic_variables` to supply per-session values that override
- the agent's stored variable defaults for this one conversation.
- Keys in the `system__` namespace are rejected at this boundary.
-
- Parameters
- ----------
- id : str
-
- transport : typing.Optional[str]
- Transport hint. Omit to use the agent's default.
-
- dynamic_variables : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
- Per-session variable overrides that merge on top of the agent's
- stored variable defaults for this one conversation. Keys in the
- reserved `system__` namespace are rejected. Values must match the
- declared type of the corresponding variable definition on the agent.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- CreateConversationResponse
- The created conversation with its realtime session token.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.create_conversation(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/conversations",
- method="POST",
- json={
- "transport": transport,
- "dynamic_variables": dynamic_variables,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- CreateConversationResponse,
- parse_obj_as(
- type_=CreateConversationResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def create_session(
- self,
- id: str,
- *,
- user_identity: typing.Optional[str] = OMIT,
- dynamic_variables: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> CreateConversationResponse:
- """
- Mint a realtime voice session for the given agent. Widget-friendly
- counterpart to `createConversation` — same response shape, dual
- authentication:
-
- * **Authenticated (Bearer)**: works for any agent the caller
- owns. Typical server-to-server flow where the embedding
- site's backend mints a token and hands it to the browser so
- the API key never reaches the client.
- * **Unauthenticated**: works only when `agent.is_public = true`
- AND the request's `Origin` header matches `agent.allowed_origins`
- (or that list is empty). When `agent.hostname_allowlist` is
- non-empty, the `Origin` hostname must additionally be a
- member of that list. Used directly by the
- `` web component.
-
- Responds with the same `CreateConversationResponse` as
- `createConversation`.
-
- Parameters
- ----------
- id : str
-
- user_identity : typing.Optional[str]
- Opaque identifier for the end-user (e.g. your app's user ID). Stamped onto the conversation. Optional - defaults to an anonymous per-session ID.
-
- dynamic_variables : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
- Per-session variable overrides that merge on top of the agent's
- stored variable defaults for this one session. Keys in the
- reserved `system__` namespace are rejected at this boundary.
- Values must match the declared type of the corresponding variable
- definition on the agent (a `string` type expects a JSON string,
- `number` expects a JSON number, etc.).
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- CreateConversationResponse
- The created session with its realtime token + URL.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.create_session(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/sessions",
- method="POST",
- json={
- "user_identity": user_identity,
- "dynamic_variables": dynamic_variables,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- CreateConversationResponse,
- parse_obj_as(
- type_=CreateConversationResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 403:
- raise ForbiddenError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_agent_knowledge_bases(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListKnowledgeBasesResponse:
- """
- List knowledge bases attached to an agent.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListKnowledgeBasesResponse
- The knowledge bases attached to the agent.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.list_agent_knowledge_bases(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/knowledge-bases",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListKnowledgeBasesResponse,
- parse_obj_as(
- type_=ListKnowledgeBasesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def attach_knowledge_base(
- self, id: str, kb_id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> None:
- """
- Attach a knowledge base to an agent. The `search_knowledge` tool
- is auto-registered on the next conversation and can only query the
- attached knowledge bases.
-
- Parameters
- ----------
- id : str
-
- kb_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.attach_knowledge_base(
- id="id",
- kb_id="kbId",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/knowledge-bases/{jsonable_encoder(kb_id)}",
- method="POST",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def detach_knowledge_base(
- self, id: str, kb_id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> None:
- """
- Detach a knowledge base from an agent.
-
- Parameters
- ----------
- id : str
-
- kb_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.detach_knowledge_base(
- id="id",
- kb_id="kbId",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/knowledge-bases/{jsonable_encoder(kb_id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_memories(
- self,
- id: str,
- *,
- limit: typing.Optional[int] = None,
- offset: typing.Optional[int] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> ListMemoriesResponse:
- """
- List per-caller memories extracted for an agent. Memories are
- written post-call by the built-in extractor when `memory_enabled`
- is true on the agent; the list is sorted newest-first.
-
- Parameters
- ----------
- id : str
-
- limit : typing.Optional[int]
- Maximum rows to return. Defaults to 100, capped at 200.
-
- offset : typing.Optional[int]
- Number of rows to skip. Combine with `limit` to page through older memories.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListMemoriesResponse
- Memories for the agent.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.list_memories(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/memories",
- method="GET",
- params={
- "limit": limit,
- "offset": offset,
- },
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListMemoriesResponse,
- parse_obj_as(
- type_=ListMemoriesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def delete_memories_by_caller(
- self, id: str, *, agent_id: str, caller_identity: str, request_options: typing.Optional[RequestOptions] = None
- ) -> DeleteMemoriesByCallerResponse:
- """
- Delete every memory ever extracted for a specific caller on
- this agent. Privacy / GDPR surface. Returns the count of rows
- soft-deleted; rows become permanently unreachable immediately
- and are hard-deleted by the retention job after the tenant's
- configured retention window.
-
- Parameters
- ----------
- id : str
-
- agent_id : str
-
- caller_identity : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeleteMemoriesByCallerResponse
- Deletion summary.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.delete_memories_by_caller(
- id="id",
- agent_id="agent_id",
- caller_identity="caller_identity",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/memories/delete-by-caller",
- method="POST",
- json={
- "agent_id": agent_id,
- "caller_identity": caller_identity,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- DeleteMemoriesByCallerResponse,
- parse_obj_as(
- type_=DeleteMemoriesByCallerResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_tests(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> ListAgentTestsResponse:
- """
- List all tests configured for the agent. Each entry includes the
- most recent run so the console can render pass/fail badges without
- an extra round-trip.
-
- Parameters
- ----------
- id : str
- Agent ID.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListAgentTestsResponse
- Tests for the agent with last-run summaries.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.list_tests(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/tests",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListAgentTestsResponse,
- parse_obj_as(
- type_=ListAgentTestsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def create_test(
- self,
- id: str,
- *,
- name: str,
- type: TestType,
- config: CreateAgentTestRequestConfig,
- description: typing.Optional[str] = OMIT,
- tool_mock_config: typing.Optional[ToolMockConfig] = OMIT,
- variables: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
- folder_id: typing.Optional[str] = OMIT,
- attached_agent_ids: typing.Optional[typing.Sequence[str]] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AgentTest:
- """
- Create a new test for the agent.
-
- Parameters
- ----------
- id : str
- Agent ID.
-
- name : str
- Short human-readable label for the test.
-
- type : TestType
-
- config : CreateAgentTestRequestConfig
- Type-specific configuration. Must match the shape for the given `type`.
-
- description : typing.Optional[str]
- Optional longer description of what this test verifies.
-
- tool_mock_config : typing.Optional[ToolMockConfig]
- Optional tool-mocking config applied during every run of this test.
-
- variables : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
- Per-test variable values substituted into string fields of the
- config at run-start. Keys use the same rules as agent-level
- `DynamicVariable` keys.
-
- folder_id : typing.Optional[str]
- Folder to place the test in. Omit for root.
-
- attached_agent_ids : typing.Optional[typing.Sequence[str]]
- Optional list of additional agents this test should also run
- against. The owner agent (path param) is always attached
- implicitly.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AgentTest
- The created test.
-
- Examples
- --------
- from speechify import Speechify
- from speechify.tts import ScenarioConfig
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.create_test(
- id="id",
- name="Greet the caller by name",
- description="Agent should greet the caller using their name when provided.",
- type="scenario",
- config=ScenarioConfig(
- context="The caller says: Hi, I'm Alice.",
- success_criteria="The agent greets Alice by name.",
- success_examples=["Hi Alice! How can I help you today?"],
- failure_examples=["Hello! How can I help you?"],
- ),
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/tests",
- method="POST",
- json={
- "name": name,
- "description": description,
- "type": type,
- "config": convert_and_respect_annotation_metadata(
- object_=config, annotation=CreateAgentTestRequestConfig, direction="write"
- ),
- "tool_mock_config": convert_and_respect_annotation_metadata(
- object_=tool_mock_config, annotation=ToolMockConfig, direction="write"
- ),
- "variables": variables,
- "folder_id": folder_id,
- "attached_agent_ids": attached_agent_ids,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AgentTest,
- parse_obj_as(
- type_=AgentTest, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def run_all_tests(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> RunAgentTestsResponse:
- """
- Enqueue runs for every test on the agent concurrently. Up to 50
- tests are dispatched in one call. Each returned run starts in
- `queued` status; poll `GET /v1/test-runs/{id}` for the terminal
- result.
-
- Parameters
- ----------
- id : str
- Agent ID.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- RunAgentTestsResponse
- Queued runs for all tests on the agent.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.run_all_tests(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/tests/runs",
- method="POST",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- RunAgentTestsResponse,
- parse_obj_as(
- type_=RunAgentTestsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def get_test(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentTest:
- """
- Retrieve a test by ID.
-
- Parameters
- ----------
- id : str
- Test ID.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AgentTest
- The requested test.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.get_test(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AgentTest,
- parse_obj_as(
- type_=AgentTest, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def delete_test(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Delete a test and all its run history.
-
- Parameters
- ----------
- id : str
- Test ID.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.delete_test(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def update_test(
- self,
- id: str,
- *,
- name: typing.Optional[str] = OMIT,
- description: typing.Optional[str] = OMIT,
- config: typing.Optional[UpdateAgentTestRequestConfig] = OMIT,
- tool_mock_config: typing.Optional[ToolMockConfig] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AgentTest:
- """
- Update a test. Only fields present on the request body are changed.
-
- Parameters
- ----------
- id : str
- Test ID.
-
- name : typing.Optional[str]
-
- description : typing.Optional[str]
-
- config : typing.Optional[UpdateAgentTestRequestConfig]
- Replaces the test config when present.
-
- tool_mock_config : typing.Optional[ToolMockConfig]
- Replaces the tool-mock config when present.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AgentTest
- The updated test.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.update_test(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}",
- method="PATCH",
- json={
- "name": name,
- "description": description,
- "config": convert_and_respect_annotation_metadata(
- object_=config, annotation=UpdateAgentTestRequestConfig, direction="write"
- ),
- "tool_mock_config": convert_and_respect_annotation_metadata(
- object_=tool_mock_config, annotation=ToolMockConfig, direction="write"
- ),
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AgentTest,
- parse_obj_as(
- type_=AgentTest, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_test_runs(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListAgentTestRunsResponse:
- """
- List the run history for a test, newest first.
-
- Parameters
- ----------
- id : str
- Test ID.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListAgentTestRunsResponse
- Run history for the test.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.list_test_runs(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}/runs",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListAgentTestRunsResponse,
- parse_obj_as(
- type_=ListAgentTestRunsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def run_test(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentTestRun:
- """
- Enqueue a single run of the test. The returned run starts in
- `queued` status. Poll `GET /v1/test-runs/{id}` until the status
- reaches a terminal state (`passed`, `failed`, or `error`).
-
- Parameters
- ----------
- id : str
- Test ID.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AgentTestRun
- The queued run.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.run_test(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}/runs",
- method="POST",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AgentTestRun,
- parse_obj_as(
- type_=AgentTestRun, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def get_test_run(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentTestRun:
- """
- Retrieve a single test run by ID. Poll this endpoint until
- `status` reaches a terminal state (`passed`, `failed`, or `error`).
- The `result` field is populated on terminal states.
-
- Parameters
- ----------
- id : str
- Test run ID.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AgentTestRun
- The test run.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.get_test_run(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/test-runs/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AgentTestRun,
- parse_obj_as(
- type_=AgentTestRun, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_all_tests(
- self,
- *,
- agent_id: typing.Optional[str] = None,
- type: typing.Optional[str] = None,
- status: typing.Optional[str] = None,
- folder_id: typing.Optional[str] = None,
- updated_after: typing.Optional[str] = None,
- q: typing.Optional[str] = None,
- limit: typing.Optional[int] = None,
- cursor: typing.Optional[str] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> ListTestsResponse:
- """
- Workspace-wide list of tests across every agent the caller owns.
- Supports filters (agent, type, last-run status, folder), full-text
- search on name/description, and cursor pagination. Each row carries
- its newest run and attached agent IDs so the list renders without
- N+1 round-trips.
-
- Parameters
- ----------
- agent_id : typing.Optional[str]
- Comma-separated agent IDs to filter on.
-
- type : typing.Optional[str]
- Comma-separated test types (scenario|tool|simulation).
-
- status : typing.Optional[str]
- Comma-separated last-run statuses.
-
- folder_id : typing.Optional[str]
- Folder ID to filter on, or "root" for unfiled tests.
-
- updated_after : typing.Optional[str]
- Only return tests updated after this RFC3339 timestamp.
-
- q : typing.Optional[str]
- Substring match on name or description.
-
- limit : typing.Optional[int]
- Max tests per page (default 50, max 200).
-
- cursor : typing.Optional[str]
- Opaque pagination cursor from a previous response.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListTestsResponse
- Paginated list.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.list_all_tests()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/tests",
- method="GET",
- params={
- "agent_id": agent_id,
- "type": type,
- "status": status,
- "folder_id": folder_id,
- "updated_after": updated_after,
- "q": q,
- "limit": limit,
- "cursor": cursor,
- },
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListTestsResponse,
- parse_obj_as(
- type_=ListTestsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def get_test_stats(
- self, *, window_days: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None
- ) -> TestStats:
- """
- Aggregate pass-rate metrics over the last N days. Returns dense
- daily buckets (one entry per day, zero-filled) plus totals and a
- per-type breakdown. Powers the header chart on the global tests
- page. Default window is 30 days, max 90.
-
- Parameters
- ----------
- window_days : typing.Optional[int]
- Trailing window in days (default 30, max 90).
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- TestStats
- Stats payload.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.get_test_stats()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/tests/stats",
- method="GET",
- params={
- "window_days": window_days,
- },
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- TestStats,
- parse_obj_as(
- type_=TestStats, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def run_tests_batch(
- self, *, entries: typing.Sequence[BatchRunEntry], request_options: typing.Optional[RequestOptions] = None
- ) -> RunBatchResponse:
- """
- Queue runs for every (test, agent) pair in the body. Entries
- without an `agent_id` fan out to every agent the test is
- attached to. Total expanded runs are capped at 100 per call.
- Each entry in the response is a queued run; poll
- `GET /v1/test-runs/{id}` for each.
-
- Parameters
- ----------
- entries : typing.Sequence[BatchRunEntry]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- RunBatchResponse
- Runs queued.
-
- Examples
- --------
- from speechify import Speechify
- from speechify.tts import BatchRunEntry
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.run_tests_batch(
- entries=[
- BatchRunEntry(
- test_id="test_id",
- )
- ],
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/tests/runs:batch",
- method="POST",
- json={
- "entries": convert_and_respect_annotation_metadata(
- object_=entries, annotation=typing.Sequence[BatchRunEntry], direction="write"
- ),
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- RunBatchResponse,
- parse_obj_as(
- type_=RunBatchResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_test_attachments(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListAgentTestAttachmentsResponse:
- """
- List every agent a test is attached to.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListAgentTestAttachmentsResponse
- Attachment list.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.list_test_attachments(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}/attachments",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListAgentTestAttachmentsResponse,
- parse_obj_as(
- type_=ListAgentTestAttachmentsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def attach_test(self, id: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Attach a test to an additional agent. After this call, the test
- will also run as part of that agent's regression suite (and
- against its prompt + tool config when invoked with
- `agent_id = {agentId}`). Idempotent.
-
- Parameters
- ----------
- id : str
-
- agent_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.attach_test(
- id="id",
- agent_id="agentId",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}/attachments/{jsonable_encoder(agent_id)}",
- method="POST",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def detach_test(self, id: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Detach a test from an agent. The owner agent (the agent the test
- was authored against) cannot be detached; delete the test
- instead.
-
- Parameters
- ----------
- id : str
-
- agent_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.detach_test(
- id="id",
- agent_id="agentId",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}/attachments/{jsonable_encoder(agent_id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def move_test(
- self,
- id: str,
- *,
- folder_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> None:
- """
- Move a test into a folder. Pass `folder_id: null` for root.
-
- Parameters
- ----------
- id : str
-
- folder_id : typing.Optional[str]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.move_test(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}/move",
- method="POST",
- json={
- "folder_id": folder_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_test_folders(
- self, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListAgentTestFoldersResponse:
- """
- List every test folder the caller owns. Flat list; build the tree client-side.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListAgentTestFoldersResponse
- Folder list.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.list_test_folders()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/test-folders",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListAgentTestFoldersResponse,
- parse_obj_as(
- type_=ListAgentTestFoldersResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def create_test_folder(
- self,
- *,
- name: str,
- parent_folder_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AgentTestFolder:
- """
- Create a test folder. Max depth is 3.
-
- Parameters
- ----------
- name : str
-
- parent_folder_id : typing.Optional[str]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AgentTestFolder
- Created folder.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.create_test_folder(
- name="name",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/test-folders",
- method="POST",
- json={
- "name": name,
- "parent_folder_id": parent_folder_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AgentTestFolder,
- parse_obj_as(
- type_=AgentTestFolder, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def delete_test_folder(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Soft-delete a folder. Child tests drop back to root.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.delete_test_folder(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/test-folders/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def update_test_folder(
- self,
- id: str,
- *,
- name: typing.Optional[str] = OMIT,
- parent_folder_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AgentTestFolder:
- """
- Rename or reparent a test folder. Cycles are rejected.
-
- Parameters
- ----------
- id : str
-
- name : typing.Optional[str]
-
- parent_folder_id : typing.Optional[str]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AgentTestFolder
- Updated folder.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.agents.update_test_folder(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/test-folders/{jsonable_encoder(id)}",
- method="PATCH",
- json={
- "name": name,
- "parent_folder_id": parent_folder_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AgentTestFolder,
- parse_obj_as(
- type_=AgentTestFolder, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
-
-class AsyncAgentsClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListAgentsResponse:
- """
- List voice agents owned by the caller.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListAgentsResponse
- A list of voice agents.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.list()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/agents",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListAgentsResponse,
- parse_obj_as(
- type_=ListAgentsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def create(
- self,
- *,
- name: str,
- voice_id: str,
- slug: typing.Optional[str] = OMIT,
- prompt: typing.Optional[str] = OMIT,
- first_message: typing.Optional[str] = OMIT,
- language: typing.Optional[str] = OMIT,
- llm_model: typing.Optional[str] = OMIT,
- temperature: typing.Optional[float] = OMIT,
- config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
- is_public: typing.Optional[bool] = OMIT,
- allowed_origins: typing.Optional[typing.Sequence[str]] = OMIT,
- hostname_allowlist: typing.Optional[typing.Sequence[str]] = OMIT,
- memory_enabled: typing.Optional[bool] = OMIT,
- memory_retention_days: typing.Optional[int] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> Agent:
- """
- Create a voice agent.
-
- Parameters
- ----------
- name : str
-
- voice_id : str
- Voice slug from the VMS catalog (see GET /v1/voices). Required — the server rejects writes with an unknown or empty slug.
-
- slug : typing.Optional[str]
- Optional. Server derives slug from name with a random suffix when omitted; if you supply your own, a collision returns 400 'slug already taken'.
-
- prompt : typing.Optional[str]
-
- first_message : typing.Optional[str]
- Spoken verbatim at session start — no LLM round trip.
-
- language : typing.Optional[str]
-
- llm_model : typing.Optional[str]
- Optional chat model slug. Leave empty to use the Speechify default.
-
- temperature : typing.Optional[float]
-
- config : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
-
- is_public : typing.Optional[bool]
-
- allowed_origins : typing.Optional[typing.Sequence[str]]
-
- hostname_allowlist : typing.Optional[typing.Sequence[str]]
- Optional per-agent hostname allowlist (see Agent schema).
-
- memory_enabled : typing.Optional[bool]
-
- memory_retention_days : typing.Optional[int]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Agent
- The created agent.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.create(
- name="name",
- voice_id="voice_id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/agents",
- method="POST",
- json={
- "name": name,
- "slug": slug,
- "prompt": prompt,
- "first_message": first_message,
- "language": language,
- "llm_model": llm_model,
- "voice_id": voice_id,
- "temperature": temperature,
- "config": config,
- "is_public": is_public,
- "allowed_origins": allowed_origins,
- "hostname_allowlist": hostname_allowlist,
- "memory_enabled": memory_enabled,
- "memory_retention_days": memory_retention_days,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Agent,
- parse_obj_as(
- type_=Agent, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Agent:
- """
- Retrieve a voice agent by ID.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Agent
- The requested agent.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.get(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Agent,
- parse_obj_as(
- type_=Agent, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Delete a voice agent. Conversations and attached tools remain.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.delete(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def update(
- self,
- id: str,
- *,
- name: typing.Optional[str] = OMIT,
- prompt: typing.Optional[str] = OMIT,
- first_message: typing.Optional[str] = OMIT,
- language: typing.Optional[str] = OMIT,
- llm_model: typing.Optional[str] = OMIT,
- voice_id: typing.Optional[str] = OMIT,
- temperature: typing.Optional[float] = OMIT,
- config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
- is_public: typing.Optional[bool] = OMIT,
- allowed_origins: typing.Optional[typing.Sequence[str]] = OMIT,
- hostname_allowlist: typing.Optional[typing.Sequence[str]] = OMIT,
- memory_enabled: typing.Optional[bool] = OMIT,
- memory_retention_days: typing.Optional[int] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> Agent:
- """
- Update a voice agent. Only fields present on the request body are changed.
-
- Parameters
- ----------
- id : str
-
- name : typing.Optional[str]
-
- prompt : typing.Optional[str]
-
- first_message : typing.Optional[str]
-
- language : typing.Optional[str]
-
- llm_model : typing.Optional[str]
-
- voice_id : typing.Optional[str]
-
- temperature : typing.Optional[float]
-
- config : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
-
- is_public : typing.Optional[bool]
-
- allowed_origins : typing.Optional[typing.Sequence[str]]
-
- hostname_allowlist : typing.Optional[typing.Sequence[str]]
- When supplied, replaces the stored list. Pass an empty
- array to clear enforcement (public agent is open again).
- Omit the field to leave the existing value unchanged.
-
- memory_enabled : typing.Optional[bool]
-
- memory_retention_days : typing.Optional[int]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Agent
- The updated agent.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.update(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}",
- method="PATCH",
- json={
- "name": name,
- "prompt": prompt,
- "first_message": first_message,
- "language": language,
- "llm_model": llm_model,
- "voice_id": voice_id,
- "temperature": temperature,
- "config": config,
- "is_public": is_public,
- "allowed_origins": allowed_origins,
- "hostname_allowlist": hostname_allowlist,
- "memory_enabled": memory_enabled,
- "memory_retention_days": memory_retention_days,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Agent,
- parse_obj_as(
- type_=Agent, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_tools(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListToolsResponse:
- """
- List tools currently attached to the agent.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListToolsResponse
- Attached tools for the agent.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.list_tools(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/tools",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListToolsResponse,
- parse_obj_as(
- type_=ListToolsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def attach_tool(
- self, id: str, tool_id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> None:
- """
- Attach an existing tool to the agent so the LLM can call it.
-
- Parameters
- ----------
- id : str
-
- tool_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.attach_tool(
- id="id",
- tool_id="toolId",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/tools/{jsonable_encoder(tool_id)}",
- method="POST",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def detach_tool(
- self, id: str, tool_id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> None:
- """
- Detach a tool from the agent.
-
- Parameters
- ----------
- id : str
-
- tool_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.detach_tool(
- id="id",
- tool_id="toolId",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/tools/{jsonable_encoder(tool_id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def get_evaluation_config(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> EvaluationConfig:
- """
- Retrieve the agent's post-call evaluation criteria + data-collection config.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- EvaluationConfig
- The evaluation config for the agent.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.get_evaluation_config(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/evaluation-config",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- EvaluationConfig,
- parse_obj_as(
- type_=EvaluationConfig, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def update_evaluation_config(
- self,
- id: str,
- *,
- criteria: typing.Sequence[EvaluationCriterion],
- data_collection: typing.Sequence[DataCollectionField],
- request_options: typing.Optional[RequestOptions] = None,
- ) -> EvaluationConfig:
- """
- Replace the agent's evaluation criteria + data-collection fields.
-
- Parameters
- ----------
- id : str
-
- criteria : typing.Sequence[EvaluationCriterion]
-
- data_collection : typing.Sequence[DataCollectionField]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- EvaluationConfig
- The updated evaluation config.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
- from speechify.tts import DataCollectionField, EvaluationCriterion
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.update_evaluation_config(
- id="id",
- criteria=[
- EvaluationCriterion(
- id="id",
- name="name",
- description="description",
- )
- ],
- data_collection=[
- DataCollectionField(
- key="key",
- description="description",
- type="string",
- )
- ],
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/evaluation-config",
- method="PATCH",
- json={
- "criteria": convert_and_respect_annotation_metadata(
- object_=criteria, annotation=typing.Sequence[EvaluationCriterion], direction="write"
- ),
- "data_collection": convert_and_respect_annotation_metadata(
- object_=data_collection, annotation=typing.Sequence[DataCollectionField], direction="write"
- ),
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- EvaluationConfig,
- parse_obj_as(
- type_=EvaluationConfig, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def get_dynamic_variables(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListDynamicVariablesResponse:
- """
- Retrieve the agent's customer-scope dynamic variables and the read-only
- catalogue of reserved `system__*` keys. The system variables list is
- provided so editor UIs can render the reference list without maintaining
- a client-side copy of the catalogue.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListDynamicVariablesResponse
- The agent's variable catalogue.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.get_dynamic_variables(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/variables",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListDynamicVariablesResponse,
- parse_obj_as(
- type_=ListDynamicVariablesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def update_dynamic_variables(
- self,
- id: str,
- *,
- variables: typing.Sequence[DynamicVariable],
- request_options: typing.Optional[RequestOptions] = None,
- ) -> ListDynamicVariablesResponse:
- """
- Replace the agent's customer-scope dynamic variable definitions.
- The supplied list overwrites the stored list wholesale (same
- semantics as `updateEvaluationConfig`). Pass an empty array to
- clear all variables. Up to 20 variables per agent. Keys must
- match `[a-zA-Z0-9_]+` and must not start with the reserved
- `system__` prefix.
-
- Parameters
- ----------
- id : str
-
- variables : typing.Sequence[DynamicVariable]
- The new variable list. Replaces the existing list entirely.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListDynamicVariablesResponse
- The updated variable catalogue.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
- from speechify.tts import DynamicVariable
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.update_dynamic_variables(
- id="id",
- variables=[
- DynamicVariable(
- key="product_name",
- type="string",
- default="Speechify",
- description="Product the agent is supporting.",
- ),
- DynamicVariable(
- key="support_tier",
- type="number",
- default=1,
- ),
- DynamicVariable(
- key="account_metadata",
- type="json",
- description="Arbitrary account context injected into tool bodies.",
- ),
- ],
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/variables",
- method="PATCH",
- json={
- "variables": convert_and_respect_annotation_metadata(
- object_=variables, annotation=typing.Sequence[DynamicVariable], direction="write"
- ),
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListDynamicVariablesResponse,
- parse_obj_as(
- type_=ListDynamicVariablesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def create_conversation(
- self,
- id: str,
- *,
- transport: typing.Optional[str] = OMIT,
- dynamic_variables: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> CreateConversationResponse:
- """
- Start a new voice conversation with the agent. Returns a realtime
- voice session + short-lived client token so the caller can
- connect the audio pipeline directly. The agent is dispatched
- server-side; no additional client action required.
-
- Pass `dynamic_variables` to supply per-session values that override
- the agent's stored variable defaults for this one conversation.
- Keys in the `system__` namespace are rejected at this boundary.
-
- Parameters
- ----------
- id : str
-
- transport : typing.Optional[str]
- Transport hint. Omit to use the agent's default.
-
- dynamic_variables : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
- Per-session variable overrides that merge on top of the agent's
- stored variable defaults for this one conversation. Keys in the
- reserved `system__` namespace are rejected. Values must match the
- declared type of the corresponding variable definition on the agent.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- CreateConversationResponse
- The created conversation with its realtime session token.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.create_conversation(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/conversations",
- method="POST",
- json={
- "transport": transport,
- "dynamic_variables": dynamic_variables,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- CreateConversationResponse,
- parse_obj_as(
- type_=CreateConversationResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def create_session(
- self,
- id: str,
- *,
- user_identity: typing.Optional[str] = OMIT,
- dynamic_variables: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> CreateConversationResponse:
- """
- Mint a realtime voice session for the given agent. Widget-friendly
- counterpart to `createConversation` — same response shape, dual
- authentication:
-
- * **Authenticated (Bearer)**: works for any agent the caller
- owns. Typical server-to-server flow where the embedding
- site's backend mints a token and hands it to the browser so
- the API key never reaches the client.
- * **Unauthenticated**: works only when `agent.is_public = true`
- AND the request's `Origin` header matches `agent.allowed_origins`
- (or that list is empty). When `agent.hostname_allowlist` is
- non-empty, the `Origin` hostname must additionally be a
- member of that list. Used directly by the
- `` web component.
-
- Responds with the same `CreateConversationResponse` as
- `createConversation`.
-
- Parameters
- ----------
- id : str
-
- user_identity : typing.Optional[str]
- Opaque identifier for the end-user (e.g. your app's user ID). Stamped onto the conversation. Optional - defaults to an anonymous per-session ID.
-
- dynamic_variables : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
- Per-session variable overrides that merge on top of the agent's
- stored variable defaults for this one session. Keys in the
- reserved `system__` namespace are rejected at this boundary.
- Values must match the declared type of the corresponding variable
- definition on the agent (a `string` type expects a JSON string,
- `number` expects a JSON number, etc.).
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- CreateConversationResponse
- The created session with its realtime token + URL.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.create_session(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/sessions",
- method="POST",
- json={
- "user_identity": user_identity,
- "dynamic_variables": dynamic_variables,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- CreateConversationResponse,
- parse_obj_as(
- type_=CreateConversationResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 403:
- raise ForbiddenError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_agent_knowledge_bases(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListKnowledgeBasesResponse:
- """
- List knowledge bases attached to an agent.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListKnowledgeBasesResponse
- The knowledge bases attached to the agent.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.list_agent_knowledge_bases(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/knowledge-bases",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListKnowledgeBasesResponse,
- parse_obj_as(
- type_=ListKnowledgeBasesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def attach_knowledge_base(
- self, id: str, kb_id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> None:
- """
- Attach a knowledge base to an agent. The `search_knowledge` tool
- is auto-registered on the next conversation and can only query the
- attached knowledge bases.
-
- Parameters
- ----------
- id : str
-
- kb_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.attach_knowledge_base(
- id="id",
- kb_id="kbId",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/knowledge-bases/{jsonable_encoder(kb_id)}",
- method="POST",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def detach_knowledge_base(
- self, id: str, kb_id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> None:
- """
- Detach a knowledge base from an agent.
-
- Parameters
- ----------
- id : str
-
- kb_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.detach_knowledge_base(
- id="id",
- kb_id="kbId",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/knowledge-bases/{jsonable_encoder(kb_id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_memories(
- self,
- id: str,
- *,
- limit: typing.Optional[int] = None,
- offset: typing.Optional[int] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> ListMemoriesResponse:
- """
- List per-caller memories extracted for an agent. Memories are
- written post-call by the built-in extractor when `memory_enabled`
- is true on the agent; the list is sorted newest-first.
-
- Parameters
- ----------
- id : str
-
- limit : typing.Optional[int]
- Maximum rows to return. Defaults to 100, capped at 200.
-
- offset : typing.Optional[int]
- Number of rows to skip. Combine with `limit` to page through older memories.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListMemoriesResponse
- Memories for the agent.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.list_memories(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/memories",
- method="GET",
- params={
- "limit": limit,
- "offset": offset,
- },
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListMemoriesResponse,
- parse_obj_as(
- type_=ListMemoriesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def delete_memories_by_caller(
- self, id: str, *, agent_id: str, caller_identity: str, request_options: typing.Optional[RequestOptions] = None
- ) -> DeleteMemoriesByCallerResponse:
- """
- Delete every memory ever extracted for a specific caller on
- this agent. Privacy / GDPR surface. Returns the count of rows
- soft-deleted; rows become permanently unreachable immediately
- and are hard-deleted by the retention job after the tenant's
- configured retention window.
-
- Parameters
- ----------
- id : str
-
- agent_id : str
-
- caller_identity : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- DeleteMemoriesByCallerResponse
- Deletion summary.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.delete_memories_by_caller(
- id="id",
- agent_id="agent_id",
- caller_identity="caller_identity",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/memories/delete-by-caller",
- method="POST",
- json={
- "agent_id": agent_id,
- "caller_identity": caller_identity,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- DeleteMemoriesByCallerResponse,
- parse_obj_as(
- type_=DeleteMemoriesByCallerResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_tests(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListAgentTestsResponse:
- """
- List all tests configured for the agent. Each entry includes the
- most recent run so the console can render pass/fail badges without
- an extra round-trip.
-
- Parameters
- ----------
- id : str
- Agent ID.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListAgentTestsResponse
- Tests for the agent with last-run summaries.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.list_tests(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/tests",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListAgentTestsResponse,
- parse_obj_as(
- type_=ListAgentTestsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def create_test(
- self,
- id: str,
- *,
- name: str,
- type: TestType,
- config: CreateAgentTestRequestConfig,
- description: typing.Optional[str] = OMIT,
- tool_mock_config: typing.Optional[ToolMockConfig] = OMIT,
- variables: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
- folder_id: typing.Optional[str] = OMIT,
- attached_agent_ids: typing.Optional[typing.Sequence[str]] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AgentTest:
- """
- Create a new test for the agent.
-
- Parameters
- ----------
- id : str
- Agent ID.
-
- name : str
- Short human-readable label for the test.
-
- type : TestType
-
- config : CreateAgentTestRequestConfig
- Type-specific configuration. Must match the shape for the given `type`.
-
- description : typing.Optional[str]
- Optional longer description of what this test verifies.
-
- tool_mock_config : typing.Optional[ToolMockConfig]
- Optional tool-mocking config applied during every run of this test.
-
- variables : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
- Per-test variable values substituted into string fields of the
- config at run-start. Keys use the same rules as agent-level
- `DynamicVariable` keys.
-
- folder_id : typing.Optional[str]
- Folder to place the test in. Omit for root.
-
- attached_agent_ids : typing.Optional[typing.Sequence[str]]
- Optional list of additional agents this test should also run
- against. The owner agent (path param) is always attached
- implicitly.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AgentTest
- The created test.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
- from speechify.tts import ScenarioConfig
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.create_test(
- id="id",
- name="Greet the caller by name",
- description="Agent should greet the caller using their name when provided.",
- type="scenario",
- config=ScenarioConfig(
- context="The caller says: Hi, I'm Alice.",
- success_criteria="The agent greets Alice by name.",
- success_examples=["Hi Alice! How can I help you today?"],
- failure_examples=["Hello! How can I help you?"],
- ),
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/tests",
- method="POST",
- json={
- "name": name,
- "description": description,
- "type": type,
- "config": convert_and_respect_annotation_metadata(
- object_=config, annotation=CreateAgentTestRequestConfig, direction="write"
- ),
- "tool_mock_config": convert_and_respect_annotation_metadata(
- object_=tool_mock_config, annotation=ToolMockConfig, direction="write"
- ),
- "variables": variables,
- "folder_id": folder_id,
- "attached_agent_ids": attached_agent_ids,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AgentTest,
- parse_obj_as(
- type_=AgentTest, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def run_all_tests(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> RunAgentTestsResponse:
- """
- Enqueue runs for every test on the agent concurrently. Up to 50
- tests are dispatched in one call. Each returned run starts in
- `queued` status; poll `GET /v1/test-runs/{id}` for the terminal
- result.
-
- Parameters
- ----------
- id : str
- Agent ID.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- RunAgentTestsResponse
- Queued runs for all tests on the agent.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.run_all_tests(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/agents/{jsonable_encoder(id)}/tests/runs",
- method="POST",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- RunAgentTestsResponse,
- parse_obj_as(
- type_=RunAgentTestsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def get_test(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentTest:
- """
- Retrieve a test by ID.
-
- Parameters
- ----------
- id : str
- Test ID.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AgentTest
- The requested test.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.get_test(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AgentTest,
- parse_obj_as(
- type_=AgentTest, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def delete_test(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Delete a test and all its run history.
-
- Parameters
- ----------
- id : str
- Test ID.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.delete_test(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def update_test(
- self,
- id: str,
- *,
- name: typing.Optional[str] = OMIT,
- description: typing.Optional[str] = OMIT,
- config: typing.Optional[UpdateAgentTestRequestConfig] = OMIT,
- tool_mock_config: typing.Optional[ToolMockConfig] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AgentTest:
- """
- Update a test. Only fields present on the request body are changed.
-
- Parameters
- ----------
- id : str
- Test ID.
-
- name : typing.Optional[str]
-
- description : typing.Optional[str]
-
- config : typing.Optional[UpdateAgentTestRequestConfig]
- Replaces the test config when present.
-
- tool_mock_config : typing.Optional[ToolMockConfig]
- Replaces the tool-mock config when present.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AgentTest
- The updated test.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.update_test(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}",
- method="PATCH",
- json={
- "name": name,
- "description": description,
- "config": convert_and_respect_annotation_metadata(
- object_=config, annotation=UpdateAgentTestRequestConfig, direction="write"
- ),
- "tool_mock_config": convert_and_respect_annotation_metadata(
- object_=tool_mock_config, annotation=ToolMockConfig, direction="write"
- ),
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AgentTest,
- parse_obj_as(
- type_=AgentTest, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_test_runs(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListAgentTestRunsResponse:
- """
- List the run history for a test, newest first.
-
- Parameters
- ----------
- id : str
- Test ID.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListAgentTestRunsResponse
- Run history for the test.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.list_test_runs(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}/runs",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListAgentTestRunsResponse,
- parse_obj_as(
- type_=ListAgentTestRunsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def run_test(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentTestRun:
- """
- Enqueue a single run of the test. The returned run starts in
- `queued` status. Poll `GET /v1/test-runs/{id}` until the status
- reaches a terminal state (`passed`, `failed`, or `error`).
-
- Parameters
- ----------
- id : str
- Test ID.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AgentTestRun
- The queued run.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.run_test(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}/runs",
- method="POST",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AgentTestRun,
- parse_obj_as(
- type_=AgentTestRun, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def get_test_run(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> AgentTestRun:
- """
- Retrieve a single test run by ID. Poll this endpoint until
- `status` reaches a terminal state (`passed`, `failed`, or `error`).
- The `result` field is populated on terminal states.
-
- Parameters
- ----------
- id : str
- Test run ID.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AgentTestRun
- The test run.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.get_test_run(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/test-runs/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AgentTestRun,
- parse_obj_as(
- type_=AgentTestRun, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_all_tests(
- self,
- *,
- agent_id: typing.Optional[str] = None,
- type: typing.Optional[str] = None,
- status: typing.Optional[str] = None,
- folder_id: typing.Optional[str] = None,
- updated_after: typing.Optional[str] = None,
- q: typing.Optional[str] = None,
- limit: typing.Optional[int] = None,
- cursor: typing.Optional[str] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> ListTestsResponse:
- """
- Workspace-wide list of tests across every agent the caller owns.
- Supports filters (agent, type, last-run status, folder), full-text
- search on name/description, and cursor pagination. Each row carries
- its newest run and attached agent IDs so the list renders without
- N+1 round-trips.
-
- Parameters
- ----------
- agent_id : typing.Optional[str]
- Comma-separated agent IDs to filter on.
-
- type : typing.Optional[str]
- Comma-separated test types (scenario|tool|simulation).
-
- status : typing.Optional[str]
- Comma-separated last-run statuses.
-
- folder_id : typing.Optional[str]
- Folder ID to filter on, or "root" for unfiled tests.
-
- updated_after : typing.Optional[str]
- Only return tests updated after this RFC3339 timestamp.
-
- q : typing.Optional[str]
- Substring match on name or description.
-
- limit : typing.Optional[int]
- Max tests per page (default 50, max 200).
-
- cursor : typing.Optional[str]
- Opaque pagination cursor from a previous response.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListTestsResponse
- Paginated list.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.list_all_tests()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/tests",
- method="GET",
- params={
- "agent_id": agent_id,
- "type": type,
- "status": status,
- "folder_id": folder_id,
- "updated_after": updated_after,
- "q": q,
- "limit": limit,
- "cursor": cursor,
- },
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListTestsResponse,
- parse_obj_as(
- type_=ListTestsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def get_test_stats(
- self, *, window_days: typing.Optional[int] = None, request_options: typing.Optional[RequestOptions] = None
- ) -> TestStats:
- """
- Aggregate pass-rate metrics over the last N days. Returns dense
- daily buckets (one entry per day, zero-filled) plus totals and a
- per-type breakdown. Powers the header chart on the global tests
- page. Default window is 30 days, max 90.
-
- Parameters
- ----------
- window_days : typing.Optional[int]
- Trailing window in days (default 30, max 90).
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- TestStats
- Stats payload.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.get_test_stats()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/tests/stats",
- method="GET",
- params={
- "window_days": window_days,
- },
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- TestStats,
- parse_obj_as(
- type_=TestStats, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def run_tests_batch(
- self, *, entries: typing.Sequence[BatchRunEntry], request_options: typing.Optional[RequestOptions] = None
- ) -> RunBatchResponse:
- """
- Queue runs for every (test, agent) pair in the body. Entries
- without an `agent_id` fan out to every agent the test is
- attached to. Total expanded runs are capped at 100 per call.
- Each entry in the response is a queued run; poll
- `GET /v1/test-runs/{id}` for each.
-
- Parameters
- ----------
- entries : typing.Sequence[BatchRunEntry]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- RunBatchResponse
- Runs queued.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
- from speechify.tts import BatchRunEntry
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.run_tests_batch(
- entries=[
- BatchRunEntry(
- test_id="test_id",
- )
- ],
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/tests/runs:batch",
- method="POST",
- json={
- "entries": convert_and_respect_annotation_metadata(
- object_=entries, annotation=typing.Sequence[BatchRunEntry], direction="write"
- ),
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- RunBatchResponse,
- parse_obj_as(
- type_=RunBatchResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_test_attachments(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListAgentTestAttachmentsResponse:
- """
- List every agent a test is attached to.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListAgentTestAttachmentsResponse
- Attachment list.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.list_test_attachments(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}/attachments",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListAgentTestAttachmentsResponse,
- parse_obj_as(
- type_=ListAgentTestAttachmentsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def attach_test(
- self, id: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> None:
- """
- Attach a test to an additional agent. After this call, the test
- will also run as part of that agent's regression suite (and
- against its prompt + tool config when invoked with
- `agent_id = {agentId}`). Idempotent.
-
- Parameters
- ----------
- id : str
-
- agent_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.attach_test(
- id="id",
- agent_id="agentId",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}/attachments/{jsonable_encoder(agent_id)}",
- method="POST",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def detach_test(
- self, id: str, agent_id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> None:
- """
- Detach a test from an agent. The owner agent (the agent the test
- was authored against) cannot be detached; delete the test
- instead.
-
- Parameters
- ----------
- id : str
-
- agent_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.detach_test(
- id="id",
- agent_id="agentId",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}/attachments/{jsonable_encoder(agent_id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def move_test(
- self,
- id: str,
- *,
- folder_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> None:
- """
- Move a test into a folder. Pass `folder_id: null` for root.
-
- Parameters
- ----------
- id : str
-
- folder_id : typing.Optional[str]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.move_test(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tests/{jsonable_encoder(id)}/move",
- method="POST",
- json={
- "folder_id": folder_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_test_folders(
- self, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListAgentTestFoldersResponse:
- """
- List every test folder the caller owns. Flat list; build the tree client-side.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListAgentTestFoldersResponse
- Folder list.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.list_test_folders()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/test-folders",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListAgentTestFoldersResponse,
- parse_obj_as(
- type_=ListAgentTestFoldersResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def create_test_folder(
- self,
- *,
- name: str,
- parent_folder_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AgentTestFolder:
- """
- Create a test folder. Max depth is 3.
-
- Parameters
- ----------
- name : str
-
- parent_folder_id : typing.Optional[str]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AgentTestFolder
- Created folder.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.create_test_folder(
- name="name",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/test-folders",
- method="POST",
- json={
- "name": name,
- "parent_folder_id": parent_folder_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AgentTestFolder,
- parse_obj_as(
- type_=AgentTestFolder, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def delete_test_folder(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Soft-delete a folder. Child tests drop back to root.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.delete_test_folder(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/test-folders/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def update_test_folder(
- self,
- id: str,
- *,
- name: typing.Optional[str] = OMIT,
- parent_folder_id: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AgentTestFolder:
- """
- Rename or reparent a test folder. Cycles are rejected.
-
- Parameters
- ----------
- id : str
-
- name : typing.Optional[str]
-
- parent_folder_id : typing.Optional[str]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AgentTestFolder
- Updated folder.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.agents.update_test_folder(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/test-folders/{jsonable_encoder(id)}",
- method="PATCH",
- json={
- "name": name,
- "parent_folder_id": parent_folder_id,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AgentTestFolder,
- parse_obj_as(
- type_=AgentTestFolder, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
diff --git a/src/speechify/tts/agents/types/__init__.py b/src/speechify/tts/agents/types/__init__.py
deleted file mode 100644
index 6b02c60..0000000
--- a/src/speechify/tts/agents/types/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from .create_agent_test_request_config import CreateAgentTestRequestConfig
-from .update_agent_test_request_config import UpdateAgentTestRequestConfig
-
-__all__ = ["CreateAgentTestRequestConfig", "UpdateAgentTestRequestConfig"]
diff --git a/src/speechify/tts/agents/types/create_agent_test_request_config.py b/src/speechify/tts/agents/types/create_agent_test_request_config.py
deleted file mode 100644
index b2d407d..0000000
--- a/src/speechify/tts/agents/types/create_agent_test_request_config.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from ...types.scenario_config import ScenarioConfig
-from ...types.tool_call_config import ToolCallConfig
-from ...types.simulation_config import SimulationConfig
-
-CreateAgentTestRequestConfig = typing.Union[ScenarioConfig, ToolCallConfig, SimulationConfig]
diff --git a/src/speechify/tts/agents/types/update_agent_test_request_config.py b/src/speechify/tts/agents/types/update_agent_test_request_config.py
deleted file mode 100644
index 67638a8..0000000
--- a/src/speechify/tts/agents/types/update_agent_test_request_config.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from ...types.scenario_config import ScenarioConfig
-from ...types.tool_call_config import ToolCallConfig
-from ...types.simulation_config import SimulationConfig
-
-UpdateAgentTestRequestConfig = typing.Union[ScenarioConfig, ToolCallConfig, SimulationConfig]
diff --git a/src/speechify/tts/audio/client.py b/src/speechify/tts/audio/client.py
index 055a5d8..786549d 100644
--- a/src/speechify/tts/audio/client.py
+++ b/src/speechify/tts/audio/client.py
@@ -4,21 +4,26 @@
from ...core.client_wrapper import SyncClientWrapper
from .types.get_speech_request_audio_format import GetSpeechRequestAudioFormat
from .types.get_speech_request_model import GetSpeechRequestModel
-from ..types.get_speech_options_request import GetSpeechOptionsRequest
+from ...types.get_speech_options_request import GetSpeechOptionsRequest
from ...core.request_options import RequestOptions
-from ..types.get_speech_response import GetSpeechResponse
+from ...types.get_speech_response import GetSpeechResponse
from ...core.serialization import convert_and_respect_annotation_metadata
from ...core.pydantic_utilities import parse_obj_as
-from ..errors.bad_request_error import BadRequestError
-from ..errors.unauthorized_error import UnauthorizedError
-from ..errors.payment_required_error import PaymentRequiredError
-from ..errors.forbidden_error import ForbiddenError
-from ..errors.internal_server_error import InternalServerError
+from ...errors.bad_request_error import BadRequestError
+from ...errors.unauthorized_error import UnauthorizedError
+from ...errors.payment_required_error import PaymentRequiredError
+from ...types.error import Error
+from ...errors.forbidden_error import ForbiddenError
+from ...errors.not_found_error import NotFoundError
+from ...errors.too_many_requests_error import TooManyRequestsError
+from ...errors.internal_server_error import InternalServerError
+from ...errors.bad_gateway_error import BadGatewayError
+from ...errors.service_unavailable_error import ServiceUnavailableError
from json.decoder import JSONDecodeError
from ...core.api_error import ApiError
from .types.stream_audio_request_accept import StreamAudioRequestAccept
from .types.get_stream_request_model import GetStreamRequestModel
-from ..types.get_stream_options_request import GetStreamOptionsRequest
+from ...types.get_stream_options_request import GetStreamOptionsRequest
from ...core.client_wrapper import AsyncClientWrapper
# this is used as the default value for optional parameters
@@ -41,7 +46,9 @@ def speech(
request_options: typing.Optional[RequestOptions] = None,
) -> GetSpeechResponse:
"""
- Gets the speech data for the given input
+ Synthesize speech audio from text or SSML. Returns the complete audio
+ file plus billing and speech-mark metadata in a single response. For
+ low-latency playback or long-form text, use POST /v1/audio/stream.
Parameters
----------
@@ -61,8 +68,7 @@ def speech(
Please refer to the list of the supported languages and recommendations regarding this parameter: https://docs.speechify.ai/docs/language-support.
model : typing.Optional[GetSpeechRequestModel]
- Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated.
- `simba-3.0` is the new streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships.
+ Model used for audio synthesis. `simba-english` is optimized for English, `simba-multilingual` for non-English or mixed input. `simba-3.0` is the streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships.
options : typing.Optional[GetSpeechOptionsRequest]
@@ -72,7 +78,7 @@ def speech(
Returns
-------
GetSpeechResponse
-
+ Synthesized speech audio for the requested input.
Examples
--------
@@ -82,8 +88,10 @@ def speech(
token="YOUR_TOKEN",
)
client.tts.audio.speech(
- input="input",
- voice_id="voice_id",
+ audio_format="mp3",
+ input="Hello! This is the Speechify text-to-speech API.",
+ model="simba-english",
+ voice_id="george",
)
"""
_response = self._client_wrapper.httpx_client.request(
@@ -137,15 +145,25 @@ def speech(
if _response.status_code == 402:
raise PaymentRequiredError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
)
if _response.status_code == 403:
raise ForbiddenError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
@@ -154,12 +172,42 @@ def speech(
),
)
)
+ if _response.status_code == 429:
+ raise TooManyRequestsError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
if _response.status_code == 500:
raise InternalServerError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 502:
+ raise BadGatewayError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 503:
+ raise ServiceUnavailableError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
@@ -181,7 +229,10 @@ def stream(
request_options: typing.Optional[RequestOptions] = None,
) -> typing.Iterator[bytes]:
"""
- Gets the stream speech for the given input
+ Synthesize speech and stream the audio back as it is generated, for
+ low-latency playback. The Accept header selects the audio container.
+ For short text where receiving the whole file at once is fine, use
+ POST /v1/audio/speech.
Parameters
----------
@@ -200,8 +251,7 @@ def stream(
Please refer to the list of the supported languages and recommendations regarding this parameter: https://docs.speechify.ai/docs/language-support.
model : typing.Optional[GetStreamRequestModel]
- Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated.
- `simba-3.0` is the new streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships.
+ Model used for audio synthesis. `simba-english` is optimized for English, `simba-multilingual` for non-English or mixed input. `simba-3.0` is the streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships.
options : typing.Optional[GetStreamOptionsRequest]
@@ -211,7 +261,7 @@ def stream(
Yields
------
typing.Iterator[bytes]
-
+ Chunked audio stream for the requested input.
Examples
--------
@@ -275,15 +325,25 @@ def stream(
if _response.status_code == 402:
raise PaymentRequiredError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
)
if _response.status_code == 403:
raise ForbiddenError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
@@ -292,12 +352,42 @@ def stream(
),
)
)
+ if _response.status_code == 429:
+ raise TooManyRequestsError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
if _response.status_code == 500:
raise InternalServerError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 502:
+ raise BadGatewayError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 503:
+ raise ServiceUnavailableError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
@@ -324,7 +414,9 @@ async def speech(
request_options: typing.Optional[RequestOptions] = None,
) -> GetSpeechResponse:
"""
- Gets the speech data for the given input
+ Synthesize speech audio from text or SSML. Returns the complete audio
+ file plus billing and speech-mark metadata in a single response. For
+ low-latency playback or long-form text, use POST /v1/audio/stream.
Parameters
----------
@@ -344,8 +436,7 @@ async def speech(
Please refer to the list of the supported languages and recommendations regarding this parameter: https://docs.speechify.ai/docs/language-support.
model : typing.Optional[GetSpeechRequestModel]
- Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated.
- `simba-3.0` is the new streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships.
+ Model used for audio synthesis. `simba-english` is optimized for English, `simba-multilingual` for non-English or mixed input. `simba-3.0` is the streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships.
options : typing.Optional[GetSpeechOptionsRequest]
@@ -355,7 +446,7 @@ async def speech(
Returns
-------
GetSpeechResponse
-
+ Synthesized speech audio for the requested input.
Examples
--------
@@ -370,8 +461,10 @@ async def speech(
async def main() -> None:
await client.tts.audio.speech(
- input="input",
- voice_id="voice_id",
+ audio_format="mp3",
+ input="Hello! This is the Speechify text-to-speech API.",
+ model="simba-english",
+ voice_id="george",
)
@@ -428,15 +521,25 @@ async def main() -> None:
if _response.status_code == 402:
raise PaymentRequiredError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
)
if _response.status_code == 403:
raise ForbiddenError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
@@ -445,12 +548,42 @@ async def main() -> None:
),
)
)
+ if _response.status_code == 429:
+ raise TooManyRequestsError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
if _response.status_code == 500:
raise InternalServerError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 502:
+ raise BadGatewayError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 503:
+ raise ServiceUnavailableError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
@@ -472,7 +605,10 @@ async def stream(
request_options: typing.Optional[RequestOptions] = None,
) -> typing.AsyncIterator[bytes]:
"""
- Gets the stream speech for the given input
+ Synthesize speech and stream the audio back as it is generated, for
+ low-latency playback. The Accept header selects the audio container.
+ For short text where receiving the whole file at once is fine, use
+ POST /v1/audio/speech.
Parameters
----------
@@ -491,8 +627,7 @@ async def stream(
Please refer to the list of the supported languages and recommendations regarding this parameter: https://docs.speechify.ai/docs/language-support.
model : typing.Optional[GetStreamRequestModel]
- Model used for audio synthesis. `simba-base` and `simba-turbo` are deprecated.
- `simba-3.0` is the new streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships.
+ Model used for audio synthesis. `simba-english` is optimized for English, `simba-multilingual` for non-English or mixed input. `simba-3.0` is the streaming-native model with lower TTFB and richer expressivity. Currently English only; multilingual coming soon. Non-English voices return 400 until multilingual support ships.
options : typing.Optional[GetStreamOptionsRequest]
@@ -502,7 +637,7 @@ async def stream(
Yields
------
typing.AsyncIterator[bytes]
-
+ Chunked audio stream for the requested input.
Examples
--------
@@ -574,15 +709,25 @@ async def main() -> None:
if _response.status_code == 402:
raise PaymentRequiredError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
)
if _response.status_code == 403:
raise ForbiddenError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 404:
+ raise NotFoundError(
typing.cast(
typing.Optional[typing.Any],
parse_obj_as(
@@ -591,12 +736,42 @@ async def main() -> None:
),
)
)
+ if _response.status_code == 429:
+ raise TooManyRequestsError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
if _response.status_code == 500:
raise InternalServerError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 502:
+ raise BadGatewayError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 503:
+ raise ServiceUnavailableError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
diff --git a/src/speechify/tts/audio/types/get_speech_request_model.py b/src/speechify/tts/audio/types/get_speech_request_model.py
index 6ff3461..da407de 100644
--- a/src/speechify/tts/audio/types/get_speech_request_model.py
+++ b/src/speechify/tts/audio/types/get_speech_request_model.py
@@ -2,6 +2,4 @@
import typing
-GetSpeechRequestModel = typing.Union[
- typing.Literal["simba-base", "simba-english", "simba-multilingual", "simba-turbo", "simba-3.0"], typing.Any
-]
+GetSpeechRequestModel = typing.Union[typing.Literal["simba-english", "simba-multilingual", "simba-3.0"], typing.Any]
diff --git a/src/speechify/tts/audio/types/get_stream_request_model.py b/src/speechify/tts/audio/types/get_stream_request_model.py
index af9c4b3..76d1582 100644
--- a/src/speechify/tts/audio/types/get_stream_request_model.py
+++ b/src/speechify/tts/audio/types/get_stream_request_model.py
@@ -2,6 +2,4 @@
import typing
-GetStreamRequestModel = typing.Union[
- typing.Literal["simba-base", "simba-english", "simba-multilingual", "simba-turbo", "simba-3.0"], typing.Any
-]
+GetStreamRequestModel = typing.Union[typing.Literal["simba-english", "simba-multilingual", "simba-3.0"], typing.Any]
diff --git a/src/speechify/tts/auth/__init__.py b/src/speechify/tts/auth/__init__.py
deleted file mode 100644
index b1b7579..0000000
--- a/src/speechify/tts/auth/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from .types import CreateAccessTokenRequestGrantType, CreateAccessTokenRequestScope
-
-__all__ = ["CreateAccessTokenRequestGrantType", "CreateAccessTokenRequestScope"]
diff --git a/src/speechify/tts/auth/client.py b/src/speechify/tts/auth/client.py
deleted file mode 100644
index d43c9c2..0000000
--- a/src/speechify/tts/auth/client.py
+++ /dev/null
@@ -1,205 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from ...core.client_wrapper import SyncClientWrapper
-from .types.create_access_token_request_grant_type import CreateAccessTokenRequestGrantType
-from .types.create_access_token_request_scope import CreateAccessTokenRequestScope
-from ...core.request_options import RequestOptions
-from ..types.access_token import AccessToken
-from ...core.pydantic_utilities import parse_obj_as
-from ..errors.bad_request_error import BadRequestError
-from ..errors.unauthorized_error import UnauthorizedError
-from json.decoder import JSONDecodeError
-from ...core.api_error import ApiError
-from ...core.client_wrapper import AsyncClientWrapper
-
-# this is used as the default value for optional parameters
-OMIT = typing.cast(typing.Any, ...)
-
-
-class AuthClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- def create_access_token(
- self,
- *,
- grant_type: CreateAccessTokenRequestGrantType,
- scope: typing.Optional[CreateAccessTokenRequestScope] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AccessToken:
- """
- WARNING: This endpoint is deprecated. Create a new API token for the logged in user.
-
- Parameters
- ----------
- grant_type : CreateAccessTokenRequestGrantType
- in: body
-
- scope : typing.Optional[CreateAccessTokenRequestScope]
- The scope, or a space-delimited list of scopes the token is requested for
- in: body
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AccessToken
- Contains the details of the token which can be used by the user to access the API
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.auth.create_access_token(
- grant_type="client_credentials",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/auth/token",
- method="POST",
- json={
- "grant_type": grant_type,
- "scope": scope,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AccessToken,
- parse_obj_as(
- type_=AccessToken, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
-
-class AsyncAuthClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def create_access_token(
- self,
- *,
- grant_type: CreateAccessTokenRequestGrantType,
- scope: typing.Optional[CreateAccessTokenRequestScope] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> AccessToken:
- """
- WARNING: This endpoint is deprecated. Create a new API token for the logged in user.
-
- Parameters
- ----------
- grant_type : CreateAccessTokenRequestGrantType
- in: body
-
- scope : typing.Optional[CreateAccessTokenRequestScope]
- The scope, or a space-delimited list of scopes the token is requested for
- in: body
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- AccessToken
- Contains the details of the token which can be used by the user to access the API
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.auth.create_access_token(
- grant_type="client_credentials",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/auth/token",
- method="POST",
- json={
- "grant_type": grant_type,
- "scope": scope,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- AccessToken,
- parse_obj_as(
- type_=AccessToken, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
diff --git a/src/speechify/tts/auth/types/__init__.py b/src/speechify/tts/auth/types/__init__.py
deleted file mode 100644
index d4ee5b2..0000000
--- a/src/speechify/tts/auth/types/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from .create_access_token_request_grant_type import CreateAccessTokenRequestGrantType
-from .create_access_token_request_scope import CreateAccessTokenRequestScope
-
-__all__ = ["CreateAccessTokenRequestGrantType", "CreateAccessTokenRequestScope"]
diff --git a/src/speechify/tts/auth/types/create_access_token_request_grant_type.py b/src/speechify/tts/auth/types/create_access_token_request_grant_type.py
deleted file mode 100644
index 9d7c254..0000000
--- a/src/speechify/tts/auth/types/create_access_token_request_grant_type.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-CreateAccessTokenRequestGrantType = typing.Union[typing.Literal["client_credentials"], typing.Any]
diff --git a/src/speechify/tts/auth/types/create_access_token_request_scope.py b/src/speechify/tts/auth/types/create_access_token_request_scope.py
deleted file mode 100644
index 6c7c11c..0000000
--- a/src/speechify/tts/auth/types/create_access_token_request_scope.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-CreateAccessTokenRequestScope = typing.Union[
- typing.Literal[
- "audio:speech", "audio:stream", "audio:all", "voices:read", "voices:create", "voices:delete", "voices:all"
- ],
- typing.Any,
-]
diff --git a/src/speechify/tts/client.py b/src/speechify/tts/client.py
index 34a8e3c..36c3574 100644
--- a/src/speechify/tts/client.py
+++ b/src/speechify/tts/client.py
@@ -2,61 +2,21 @@
from ..core.client_wrapper import SyncClientWrapper
from .audio.client import AudioClient
-from .auth.client import AuthClient
from .voices.client import VoicesClient
-from .agents.client import AgentsClient
-from .tools.client import ToolsClient
-from .conversations.client import ConversationsClient
-from .knowledge_bases.client import KnowledgeBasesClient
-from .memories.client import MemoriesClient
-from .phone_numbers.client import PhoneNumbersClient
-from .sip_trunks.client import SipTrunksClient
-from .outbound_calls.client import OutboundCallsClient
-from .workspaces.client import WorkspacesClient
from ..core.client_wrapper import AsyncClientWrapper
from .audio.client import AsyncAudioClient
-from .auth.client import AsyncAuthClient
from .voices.client import AsyncVoicesClient
-from .agents.client import AsyncAgentsClient
-from .tools.client import AsyncToolsClient
-from .conversations.client import AsyncConversationsClient
-from .knowledge_bases.client import AsyncKnowledgeBasesClient
-from .memories.client import AsyncMemoriesClient
-from .phone_numbers.client import AsyncPhoneNumbersClient
-from .sip_trunks.client import AsyncSipTrunksClient
-from .outbound_calls.client import AsyncOutboundCallsClient
-from .workspaces.client import AsyncWorkspacesClient
class TtsClient:
def __init__(self, *, client_wrapper: SyncClientWrapper):
self._client_wrapper = client_wrapper
self.audio = AudioClient(client_wrapper=self._client_wrapper)
- self.auth = AuthClient(client_wrapper=self._client_wrapper)
self.voices = VoicesClient(client_wrapper=self._client_wrapper)
- self.agents = AgentsClient(client_wrapper=self._client_wrapper)
- self.tools = ToolsClient(client_wrapper=self._client_wrapper)
- self.conversations = ConversationsClient(client_wrapper=self._client_wrapper)
- self.knowledge_bases = KnowledgeBasesClient(client_wrapper=self._client_wrapper)
- self.memories = MemoriesClient(client_wrapper=self._client_wrapper)
- self.phone_numbers = PhoneNumbersClient(client_wrapper=self._client_wrapper)
- self.sip_trunks = SipTrunksClient(client_wrapper=self._client_wrapper)
- self.outbound_calls = OutboundCallsClient(client_wrapper=self._client_wrapper)
- self.workspaces = WorkspacesClient(client_wrapper=self._client_wrapper)
class AsyncTtsClient:
def __init__(self, *, client_wrapper: AsyncClientWrapper):
self._client_wrapper = client_wrapper
self.audio = AsyncAudioClient(client_wrapper=self._client_wrapper)
- self.auth = AsyncAuthClient(client_wrapper=self._client_wrapper)
self.voices = AsyncVoicesClient(client_wrapper=self._client_wrapper)
- self.agents = AsyncAgentsClient(client_wrapper=self._client_wrapper)
- self.tools = AsyncToolsClient(client_wrapper=self._client_wrapper)
- self.conversations = AsyncConversationsClient(client_wrapper=self._client_wrapper)
- self.knowledge_bases = AsyncKnowledgeBasesClient(client_wrapper=self._client_wrapper)
- self.memories = AsyncMemoriesClient(client_wrapper=self._client_wrapper)
- self.phone_numbers = AsyncPhoneNumbersClient(client_wrapper=self._client_wrapper)
- self.sip_trunks = AsyncSipTrunksClient(client_wrapper=self._client_wrapper)
- self.outbound_calls = AsyncOutboundCallsClient(client_wrapper=self._client_wrapper)
- self.workspaces = AsyncWorkspacesClient(client_wrapper=self._client_wrapper)
diff --git a/src/speechify/tts/conversations/__init__.py b/src/speechify/tts/conversations/__init__.py
deleted file mode 100644
index f3ea265..0000000
--- a/src/speechify/tts/conversations/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
diff --git a/src/speechify/tts/conversations/client.py b/src/speechify/tts/conversations/client.py
deleted file mode 100644
index 9fe6ab8..0000000
--- a/src/speechify/tts/conversations/client.py
+++ /dev/null
@@ -1,824 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.client_wrapper import SyncClientWrapper
-import typing
-from ...core.request_options import RequestOptions
-from ..types.list_conversations_response import ListConversationsResponse
-from ...core.pydantic_utilities import parse_obj_as
-from ..errors.unauthorized_error import UnauthorizedError
-from json.decoder import JSONDecodeError
-from ...core.api_error import ApiError
-from ..types.conversation_stats import ConversationStats
-from ..types.conversation import Conversation
-from ...core.jsonable_encoder import jsonable_encoder
-from ..errors.not_found_error import NotFoundError
-from ..types.list_messages_response import ListMessagesResponse
-from ..types.list_evaluations_response import ListEvaluationsResponse
-from ..types.list_memories_response import ListMemoriesResponse
-from ...core.client_wrapper import AsyncClientWrapper
-
-
-class ConversationsClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListConversationsResponse:
- """
- List conversations owned by the caller, ordered by most recent.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListConversationsResponse
- A list of conversations.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.conversations.list()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/conversations",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListConversationsResponse,
- parse_obj_as(
- type_=ListConversationsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def stats(self, *, request_options: typing.Optional[RequestOptions] = None) -> ConversationStats:
- """
- Aggregated counts and averages over the caller's conversations, scoped by the same filters as the list endpoint.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ConversationStats
- Stats for the matched conversations.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.conversations.stats()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/conversations/stats",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ConversationStats,
- parse_obj_as(
- type_=ConversationStats, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Conversation:
- """
- Retrieve a conversation by ID.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Conversation
- The requested conversation.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.conversations.get(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/conversations/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Conversation,
- parse_obj_as(
- type_=Conversation, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_messages(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListMessagesResponse:
- """
- Retrieve the full transcript for a conversation, in order.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListMessagesResponse
- The messages for the conversation.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.conversations.list_messages(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/conversations/{jsonable_encoder(id)}/messages",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListMessagesResponse,
- parse_obj_as(
- type_=ListMessagesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_evaluations(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListEvaluationsResponse:
- """
- Retrieve post-call evaluation results for a conversation.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListEvaluationsResponse
- The evaluations for the conversation.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.conversations.list_evaluations(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/conversations/{jsonable_encoder(id)}/evaluations",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListEvaluationsResponse,
- parse_obj_as(
- type_=ListEvaluationsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_memories(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListMemoriesResponse:
- """
- List memories extracted from a specific conversation.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListMemoriesResponse
- Memories written during this conversation.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.conversations.list_memories(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/conversations/{jsonable_encoder(id)}/memories",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListMemoriesResponse,
- parse_obj_as(
- type_=ListMemoriesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
-
-class AsyncConversationsClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListConversationsResponse:
- """
- List conversations owned by the caller, ordered by most recent.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListConversationsResponse
- A list of conversations.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.conversations.list()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/conversations",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListConversationsResponse,
- parse_obj_as(
- type_=ListConversationsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def stats(self, *, request_options: typing.Optional[RequestOptions] = None) -> ConversationStats:
- """
- Aggregated counts and averages over the caller's conversations, scoped by the same filters as the list endpoint.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ConversationStats
- Stats for the matched conversations.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.conversations.stats()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/conversations/stats",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ConversationStats,
- parse_obj_as(
- type_=ConversationStats, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Conversation:
- """
- Retrieve a conversation by ID.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Conversation
- The requested conversation.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.conversations.get(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/conversations/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Conversation,
- parse_obj_as(
- type_=Conversation, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_messages(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListMessagesResponse:
- """
- Retrieve the full transcript for a conversation, in order.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListMessagesResponse
- The messages for the conversation.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.conversations.list_messages(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/conversations/{jsonable_encoder(id)}/messages",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListMessagesResponse,
- parse_obj_as(
- type_=ListMessagesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_evaluations(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListEvaluationsResponse:
- """
- Retrieve post-call evaluation results for a conversation.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListEvaluationsResponse
- The evaluations for the conversation.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.conversations.list_evaluations(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/conversations/{jsonable_encoder(id)}/evaluations",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListEvaluationsResponse,
- parse_obj_as(
- type_=ListEvaluationsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_memories(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListMemoriesResponse:
- """
- List memories extracted from a specific conversation.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListMemoriesResponse
- Memories written during this conversation.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.conversations.list_memories(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/conversations/{jsonable_encoder(id)}/memories",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListMemoriesResponse,
- parse_obj_as(
- type_=ListMemoriesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
diff --git a/src/speechify/tts/errors/conflict_error.py b/src/speechify/tts/errors/conflict_error.py
deleted file mode 100644
index d7a46cb..0000000
--- a/src/speechify/tts/errors/conflict_error.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.api_error import ApiError
-import typing
-
-
-class ConflictError(ApiError):
- def __init__(self, body: typing.Optional[typing.Any]):
- super().__init__(status_code=409, body=body)
diff --git a/src/speechify/tts/errors/content_too_large_error.py b/src/speechify/tts/errors/content_too_large_error.py
deleted file mode 100644
index d418735..0000000
--- a/src/speechify/tts/errors/content_too_large_error.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.api_error import ApiError
-import typing
-
-
-class ContentTooLargeError(ApiError):
- def __init__(self, body: typing.Optional[typing.Any]):
- super().__init__(status_code=413, body=body)
diff --git a/src/speechify/tts/knowledge_bases/__init__.py b/src/speechify/tts/knowledge_bases/__init__.py
deleted file mode 100644
index f3ea265..0000000
--- a/src/speechify/tts/knowledge_bases/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
diff --git a/src/speechify/tts/knowledge_bases/client.py b/src/speechify/tts/knowledge_bases/client.py
deleted file mode 100644
index 534ae91..0000000
--- a/src/speechify/tts/knowledge_bases/client.py
+++ /dev/null
@@ -1,1722 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from ...core.client_wrapper import SyncClientWrapper
-from ...core.request_options import RequestOptions
-from ..types.list_knowledge_bases_response import ListKnowledgeBasesResponse
-from ...core.pydantic_utilities import parse_obj_as
-from ..errors.unauthorized_error import UnauthorizedError
-from json.decoder import JSONDecodeError
-from ...core.api_error import ApiError
-from ..types.knowledge_base import KnowledgeBase
-from ..errors.bad_request_error import BadRequestError
-from ...core.jsonable_encoder import jsonable_encoder
-from ..errors.not_found_error import NotFoundError
-from ..types.list_knowledge_base_documents_response import ListKnowledgeBaseDocumentsResponse
-from ... import core
-from ..types.knowledge_base_document import KnowledgeBaseDocument
-from ..errors.content_too_large_error import ContentTooLargeError
-from ..types.list_knowledge_base_chunks_response import ListKnowledgeBaseChunksResponse
-from ..types.search_knowledge_bases_response import SearchKnowledgeBasesResponse
-from ...core.client_wrapper import AsyncClientWrapper
-
-# this is used as the default value for optional parameters
-OMIT = typing.cast(typing.Any, ...)
-
-
-class KnowledgeBasesClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListKnowledgeBasesResponse:
- """
- List knowledge bases owned by the caller.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListKnowledgeBasesResponse
- The knowledge bases for the caller.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.knowledge_bases.list()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/knowledge-bases",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListKnowledgeBasesResponse,
- parse_obj_as(
- type_=ListKnowledgeBasesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def create(
- self,
- *,
- name: str,
- description: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> KnowledgeBase:
- """
- Create a new knowledge base.
-
- Parameters
- ----------
- name : str
- Human-readable label.
-
- description : typing.Optional[str]
- Optional description.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- KnowledgeBase
- The created knowledge base.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.knowledge_bases.create(
- name="name",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/knowledge-bases",
- method="POST",
- json={
- "name": name,
- "description": description,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- KnowledgeBase,
- parse_obj_as(
- type_=KnowledgeBase, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> KnowledgeBase:
- """
- Retrieve a knowledge base by ID.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- KnowledgeBase
- The requested knowledge base.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.knowledge_bases.get(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- KnowledgeBase,
- parse_obj_as(
- type_=KnowledgeBase, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Soft-delete a knowledge base. Documents and chunks are cascaded.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.knowledge_bases.delete(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def update(
- self,
- id: str,
- *,
- name: typing.Optional[str] = OMIT,
- description: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> KnowledgeBase:
- """
- Update a knowledge base.
-
- Parameters
- ----------
- id : str
-
- name : typing.Optional[str]
-
- description : typing.Optional[str]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- KnowledgeBase
- The updated knowledge base.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.knowledge_bases.update(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/{jsonable_encoder(id)}",
- method="PATCH",
- json={
- "name": name,
- "description": description,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- KnowledgeBase,
- parse_obj_as(
- type_=KnowledgeBase, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_documents(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListKnowledgeBaseDocumentsResponse:
- """
- List documents ingested into a knowledge base.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListKnowledgeBaseDocumentsResponse
- The documents in the knowledge base.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.knowledge_bases.list_documents(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/{jsonable_encoder(id)}/documents",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListKnowledgeBaseDocumentsResponse,
- parse_obj_as(
- type_=ListKnowledgeBaseDocumentsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def upload_document(
- self, id: str, *, file: core.File, request_options: typing.Optional[RequestOptions] = None
- ) -> KnowledgeBaseDocument:
- """
- Upload a document (PDF, plain text, markdown, or HTML) to a
- knowledge base. The document is extracted, chunked, embedded, and
- indexed synchronously; expect a few seconds per MB of input.
- Maximum 10 MB per upload.
-
- Parameters
- ----------
- id : str
-
- file : core.File
- See core.File for more documentation
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- KnowledgeBaseDocument
- The ingested document record.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.knowledge_bases.upload_document(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/{jsonable_encoder(id)}/documents",
- method="POST",
- data={},
- files={
- "file": file,
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- KnowledgeBaseDocument,
- parse_obj_as(
- type_=KnowledgeBaseDocument, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 413:
- raise ContentTooLargeError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def get_document(
- self, doc_id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> KnowledgeBaseDocument:
- """
- Retrieve a document by ID.
-
- Parameters
- ----------
- doc_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- KnowledgeBaseDocument
- The document record.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.knowledge_bases.get_document(
- doc_id="docId",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/documents/{jsonable_encoder(doc_id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- KnowledgeBaseDocument,
- parse_obj_as(
- type_=KnowledgeBaseDocument, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def delete_document(self, doc_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Delete a document and all its chunks.
-
- Parameters
- ----------
- doc_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.knowledge_bases.delete_document(
- doc_id="docId",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/documents/{jsonable_encoder(doc_id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_chunks(
- self, doc_id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListKnowledgeBaseChunksResponse:
- """
- List the chunks for a document.
-
- Parameters
- ----------
- doc_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListKnowledgeBaseChunksResponse
- The chunks for the document.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.knowledge_bases.list_chunks(
- doc_id="docId",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/documents/{jsonable_encoder(doc_id)}/chunks",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListKnowledgeBaseChunksResponse,
- parse_obj_as(
- type_=ListKnowledgeBaseChunksResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def search(
- self,
- *,
- query: str,
- kb_ids: typing.Sequence[str],
- top_k: typing.Optional[int] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> SearchKnowledgeBasesResponse:
- """
- Semantic search across a caller-owned list of knowledge bases.
- Returns ranked chunks with source filename and a cosine-similarity
- score. Limited to 50 results per request.
-
- Parameters
- ----------
- query : str
- Natural-language search query.
-
- kb_ids : typing.Sequence[str]
- Knowledge bases to search across. Results scoped to caller-owned entries; unknown IDs are silently ignored.
-
- top_k : typing.Optional[int]
- Max hits to return (default 5, capped at 50).
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- SearchKnowledgeBasesResponse
- Ranked search hits across the selected knowledge bases.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.knowledge_bases.search(
- query="query",
- kb_ids=["kb_ids"],
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/knowledge-bases/search",
- method="POST",
- json={
- "query": query,
- "kb_ids": kb_ids,
- "top_k": top_k,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- SearchKnowledgeBasesResponse,
- parse_obj_as(
- type_=SearchKnowledgeBasesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
-
-class AsyncKnowledgeBasesClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListKnowledgeBasesResponse:
- """
- List knowledge bases owned by the caller.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListKnowledgeBasesResponse
- The knowledge bases for the caller.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.knowledge_bases.list()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/knowledge-bases",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListKnowledgeBasesResponse,
- parse_obj_as(
- type_=ListKnowledgeBasesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def create(
- self,
- *,
- name: str,
- description: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> KnowledgeBase:
- """
- Create a new knowledge base.
-
- Parameters
- ----------
- name : str
- Human-readable label.
-
- description : typing.Optional[str]
- Optional description.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- KnowledgeBase
- The created knowledge base.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.knowledge_bases.create(
- name="name",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/knowledge-bases",
- method="POST",
- json={
- "name": name,
- "description": description,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- KnowledgeBase,
- parse_obj_as(
- type_=KnowledgeBase, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> KnowledgeBase:
- """
- Retrieve a knowledge base by ID.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- KnowledgeBase
- The requested knowledge base.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.knowledge_bases.get(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- KnowledgeBase,
- parse_obj_as(
- type_=KnowledgeBase, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Soft-delete a knowledge base. Documents and chunks are cascaded.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.knowledge_bases.delete(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def update(
- self,
- id: str,
- *,
- name: typing.Optional[str] = OMIT,
- description: typing.Optional[str] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> KnowledgeBase:
- """
- Update a knowledge base.
-
- Parameters
- ----------
- id : str
-
- name : typing.Optional[str]
-
- description : typing.Optional[str]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- KnowledgeBase
- The updated knowledge base.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.knowledge_bases.update(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/{jsonable_encoder(id)}",
- method="PATCH",
- json={
- "name": name,
- "description": description,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- KnowledgeBase,
- parse_obj_as(
- type_=KnowledgeBase, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_documents(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListKnowledgeBaseDocumentsResponse:
- """
- List documents ingested into a knowledge base.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListKnowledgeBaseDocumentsResponse
- The documents in the knowledge base.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.knowledge_bases.list_documents(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/{jsonable_encoder(id)}/documents",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListKnowledgeBaseDocumentsResponse,
- parse_obj_as(
- type_=ListKnowledgeBaseDocumentsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def upload_document(
- self, id: str, *, file: core.File, request_options: typing.Optional[RequestOptions] = None
- ) -> KnowledgeBaseDocument:
- """
- Upload a document (PDF, plain text, markdown, or HTML) to a
- knowledge base. The document is extracted, chunked, embedded, and
- indexed synchronously; expect a few seconds per MB of input.
- Maximum 10 MB per upload.
-
- Parameters
- ----------
- id : str
-
- file : core.File
- See core.File for more documentation
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- KnowledgeBaseDocument
- The ingested document record.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.knowledge_bases.upload_document(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/{jsonable_encoder(id)}/documents",
- method="POST",
- data={},
- files={
- "file": file,
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- KnowledgeBaseDocument,
- parse_obj_as(
- type_=KnowledgeBaseDocument, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 413:
- raise ContentTooLargeError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def get_document(
- self, doc_id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> KnowledgeBaseDocument:
- """
- Retrieve a document by ID.
-
- Parameters
- ----------
- doc_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- KnowledgeBaseDocument
- The document record.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.knowledge_bases.get_document(
- doc_id="docId",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/documents/{jsonable_encoder(doc_id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- KnowledgeBaseDocument,
- parse_obj_as(
- type_=KnowledgeBaseDocument, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def delete_document(self, doc_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Delete a document and all its chunks.
-
- Parameters
- ----------
- doc_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.knowledge_bases.delete_document(
- doc_id="docId",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/documents/{jsonable_encoder(doc_id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_chunks(
- self, doc_id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> ListKnowledgeBaseChunksResponse:
- """
- List the chunks for a document.
-
- Parameters
- ----------
- doc_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListKnowledgeBaseChunksResponse
- The chunks for the document.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.knowledge_bases.list_chunks(
- doc_id="docId",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/knowledge-bases/documents/{jsonable_encoder(doc_id)}/chunks",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListKnowledgeBaseChunksResponse,
- parse_obj_as(
- type_=ListKnowledgeBaseChunksResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def search(
- self,
- *,
- query: str,
- kb_ids: typing.Sequence[str],
- top_k: typing.Optional[int] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> SearchKnowledgeBasesResponse:
- """
- Semantic search across a caller-owned list of knowledge bases.
- Returns ranked chunks with source filename and a cosine-similarity
- score. Limited to 50 results per request.
-
- Parameters
- ----------
- query : str
- Natural-language search query.
-
- kb_ids : typing.Sequence[str]
- Knowledge bases to search across. Results scoped to caller-owned entries; unknown IDs are silently ignored.
-
- top_k : typing.Optional[int]
- Max hits to return (default 5, capped at 50).
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- SearchKnowledgeBasesResponse
- Ranked search hits across the selected knowledge bases.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.knowledge_bases.search(
- query="query",
- kb_ids=["kb_ids"],
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/knowledge-bases/search",
- method="POST",
- json={
- "query": query,
- "kb_ids": kb_ids,
- "top_k": top_k,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- SearchKnowledgeBasesResponse,
- parse_obj_as(
- type_=SearchKnowledgeBasesResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
diff --git a/src/speechify/tts/memories/__init__.py b/src/speechify/tts/memories/__init__.py
deleted file mode 100644
index f3ea265..0000000
--- a/src/speechify/tts/memories/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
diff --git a/src/speechify/tts/memories/client.py b/src/speechify/tts/memories/client.py
deleted file mode 100644
index afb9f84..0000000
--- a/src/speechify/tts/memories/client.py
+++ /dev/null
@@ -1,148 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.client_wrapper import SyncClientWrapper
-import typing
-from ...core.request_options import RequestOptions
-from ...core.jsonable_encoder import jsonable_encoder
-from ..errors.unauthorized_error import UnauthorizedError
-from ...core.pydantic_utilities import parse_obj_as
-from ..errors.not_found_error import NotFoundError
-from json.decoder import JSONDecodeError
-from ...core.api_error import ApiError
-from ...core.client_wrapper import AsyncClientWrapper
-
-
-class MemoriesClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- def delete(self, memory_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Soft-delete one memory row.
-
- Parameters
- ----------
- memory_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.memories.delete(
- memory_id="memoryId",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/memories/{jsonable_encoder(memory_id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
-
-class AsyncMemoriesClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def delete(self, memory_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Soft-delete one memory row.
-
- Parameters
- ----------
- memory_id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.memories.delete(
- memory_id="memoryId",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/memories/{jsonable_encoder(memory_id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
diff --git a/src/speechify/tts/outbound_calls/__init__.py b/src/speechify/tts/outbound_calls/__init__.py
deleted file mode 100644
index f3ea265..0000000
--- a/src/speechify/tts/outbound_calls/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
diff --git a/src/speechify/tts/outbound_calls/client.py b/src/speechify/tts/outbound_calls/client.py
deleted file mode 100644
index d8f9e3b..0000000
--- a/src/speechify/tts/outbound_calls/client.py
+++ /dev/null
@@ -1,213 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from ...core.client_wrapper import SyncClientWrapper
-from ...core.request_options import RequestOptions
-from ...core.pydantic_utilities import parse_obj_as
-from ..errors.bad_request_error import BadRequestError
-from ..errors.unauthorized_error import UnauthorizedError
-from ..errors.not_found_error import NotFoundError
-from json.decoder import JSONDecodeError
-from ...core.api_error import ApiError
-from ...core.client_wrapper import AsyncClientWrapper
-
-# this is used as the default value for optional parameters
-OMIT = typing.cast(typing.Any, ...)
-
-
-class OutboundCallsClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- def create(
- self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None
- ) -> typing.Optional[typing.Any]:
- """
- Place an outbound call from an agent to a phone number. LiveKit
- originates the SIP INVITE through the outbound trunk bound to the
- agent's workspace; the agent worker is dispatched into the room
- automatically.
-
- The response is returned as soon as LiveKit accepts the INVITE.
- Poll `GET /v1/conversations/{conversation_id}` for status
- transitions: `pending` → `active` (answered) → `completed`.
-
- Requires a Twilio or BYOC trunk. LiveKit-native numbers are
- inbound-only.
-
- Parameters
- ----------
- request : typing.Optional[typing.Any]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The outbound call was accepted by LiveKit.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.outbound_calls.create(
- request={"key": "value"},
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/outbound-calls",
- method="POST",
- json=request,
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
-
-class AsyncOutboundCallsClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def create(
- self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None
- ) -> typing.Optional[typing.Any]:
- """
- Place an outbound call from an agent to a phone number. LiveKit
- originates the SIP INVITE through the outbound trunk bound to the
- agent's workspace; the agent worker is dispatched into the room
- automatically.
-
- The response is returned as soon as LiveKit accepts the INVITE.
- Poll `GET /v1/conversations/{conversation_id}` for status
- transitions: `pending` → `active` (answered) → `completed`.
-
- Requires a Twilio or BYOC trunk. LiveKit-native numbers are
- inbound-only.
-
- Parameters
- ----------
- request : typing.Optional[typing.Any]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The outbound call was accepted by LiveKit.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.outbound_calls.create(
- request={"key": "value"},
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/outbound-calls",
- method="POST",
- json=request,
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
diff --git a/src/speechify/tts/phone_numbers/__init__.py b/src/speechify/tts/phone_numbers/__init__.py
deleted file mode 100644
index f3ea265..0000000
--- a/src/speechify/tts/phone_numbers/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
diff --git a/src/speechify/tts/phone_numbers/client.py b/src/speechify/tts/phone_numbers/client.py
deleted file mode 100644
index 956091a..0000000
--- a/src/speechify/tts/phone_numbers/client.py
+++ /dev/null
@@ -1,787 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from ...core.client_wrapper import SyncClientWrapper
-from ...core.request_options import RequestOptions
-from ...core.pydantic_utilities import parse_obj_as
-from ..errors.unauthorized_error import UnauthorizedError
-from json.decoder import JSONDecodeError
-from ...core.api_error import ApiError
-from ..errors.bad_request_error import BadRequestError
-from ..errors.payment_required_error import PaymentRequiredError
-from ...core.jsonable_encoder import jsonable_encoder
-from ..errors.not_found_error import NotFoundError
-from ...core.client_wrapper import AsyncClientWrapper
-
-# this is used as the default value for optional parameters
-OMIT = typing.cast(typing.Any, ...)
-
-
-class PhoneNumbersClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Optional[typing.Any]:
- """
- List all phone numbers in the caller's workspace.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The phone numbers for the workspace.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.phone_numbers.list()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/phone-numbers",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def import_(
- self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None
- ) -> typing.Optional[typing.Any]:
- """
- Import a phone number into the workspace. The `source` field
- determines the provisioning path:
-
- - `livekit` - LiveKit purchases the number on your behalf. US
- inbound only. Quickest path for local testing.
- - `twilio` - Provide your Twilio Account SID, Auth Token, and
- the E.164 number you already own. We provision an Elastic SIP
- Trunk on your Twilio account automatically.
- - `byoc` - Provide an existing SIP trunk ID. The number is
- registered against that trunk.
-
- Returns 402 when the workspace has reached the 100-number cap.
-
- Parameters
- ----------
- request : typing.Optional[typing.Any]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The imported phone number.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.phone_numbers.import_(
- request={"key": "value"},
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/phone-numbers",
- method="POST",
- json=request,
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 402:
- raise PaymentRequiredError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Optional[typing.Any]:
- """
- Retrieve a phone number by ID.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The requested phone number.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.phone_numbers.get(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/phone-numbers/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Delete a phone number from the workspace. For Twilio and LiveKit
- numbers this also deprovisions the backing SIP trunk and dispatch
- rule on LiveKit Cloud.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.phone_numbers.delete(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/phone-numbers/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def update(
- self,
- id: str,
- *,
- request: typing.Optional[typing.Any] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> typing.Optional[typing.Any]:
- """
- Update a phone number. Only `label` and `agent_id` are mutable;
- `source` and `e164` are immutable after import. Pass `null` for
- `agent_id` to unbind the number from its current agent.
-
- Parameters
- ----------
- id : str
-
- request : typing.Optional[typing.Any]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The updated phone number.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.phone_numbers.update(
- id="id",
- request={"key": "value"},
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/phone-numbers/{jsonable_encoder(id)}",
- method="PATCH",
- json=request,
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
-
-class AsyncPhoneNumbersClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Optional[typing.Any]:
- """
- List all phone numbers in the caller's workspace.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The phone numbers for the workspace.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.phone_numbers.list()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/phone-numbers",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def import_(
- self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None
- ) -> typing.Optional[typing.Any]:
- """
- Import a phone number into the workspace. The `source` field
- determines the provisioning path:
-
- - `livekit` - LiveKit purchases the number on your behalf. US
- inbound only. Quickest path for local testing.
- - `twilio` - Provide your Twilio Account SID, Auth Token, and
- the E.164 number you already own. We provision an Elastic SIP
- Trunk on your Twilio account automatically.
- - `byoc` - Provide an existing SIP trunk ID. The number is
- registered against that trunk.
-
- Returns 402 when the workspace has reached the 100-number cap.
-
- Parameters
- ----------
- request : typing.Optional[typing.Any]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The imported phone number.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.phone_numbers.import_(
- request={"key": "value"},
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/phone-numbers",
- method="POST",
- json=request,
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 402:
- raise PaymentRequiredError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def get(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> typing.Optional[typing.Any]:
- """
- Retrieve a phone number by ID.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The requested phone number.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.phone_numbers.get(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/phone-numbers/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Delete a phone number from the workspace. For Twilio and LiveKit
- numbers this also deprovisions the backing SIP trunk and dispatch
- rule on LiveKit Cloud.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.phone_numbers.delete(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/phone-numbers/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def update(
- self,
- id: str,
- *,
- request: typing.Optional[typing.Any] = None,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> typing.Optional[typing.Any]:
- """
- Update a phone number. Only `label` and `agent_id` are mutable;
- `source` and `e164` are immutable after import. Pass `null` for
- `agent_id` to unbind the number from its current agent.
-
- Parameters
- ----------
- id : str
-
- request : typing.Optional[typing.Any]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The updated phone number.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.phone_numbers.update(
- id="id",
- request={"key": "value"},
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/phone-numbers/{jsonable_encoder(id)}",
- method="PATCH",
- json=request,
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
diff --git a/src/speechify/tts/sip_trunks/__init__.py b/src/speechify/tts/sip_trunks/__init__.py
deleted file mode 100644
index f3ea265..0000000
--- a/src/speechify/tts/sip_trunks/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
diff --git a/src/speechify/tts/sip_trunks/client.py b/src/speechify/tts/sip_trunks/client.py
deleted file mode 100644
index 2d837a8..0000000
--- a/src/speechify/tts/sip_trunks/client.py
+++ /dev/null
@@ -1,589 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from ...core.client_wrapper import SyncClientWrapper
-from ...core.request_options import RequestOptions
-from ...core.pydantic_utilities import parse_obj_as
-from ..errors.unauthorized_error import UnauthorizedError
-from json.decoder import JSONDecodeError
-from ...core.api_error import ApiError
-from ..errors.bad_request_error import BadRequestError
-from ..errors.payment_required_error import PaymentRequiredError
-from ...core.jsonable_encoder import jsonable_encoder
-from ..errors.not_found_error import NotFoundError
-from ...core.client_wrapper import AsyncClientWrapper
-
-# this is used as the default value for optional parameters
-OMIT = typing.cast(typing.Any, ...)
-
-
-class SipTrunksClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Optional[typing.Any]:
- """
- List all SIP trunks in the caller's workspace.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The SIP trunks for the workspace.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.sip_trunks.list()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/sip-trunks",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def create(
- self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None
- ) -> typing.Optional[typing.Any]:
- """
- Create a SIP trunk. For `kind=byoc` supply `sip_address` plus
- optional digest credentials and IP allowlist. For `kind=twilio`
- use `ImportPhoneNumber` with a `twilio` spec instead - trunk
- creation is handled automatically. Returns 402 when the workspace
- has reached the 20-trunk cap.
-
- Parameters
- ----------
- request : typing.Optional[typing.Any]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The created SIP trunk.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.sip_trunks.create(
- request={"key": "value"},
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/sip-trunks",
- method="POST",
- json=request,
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 402:
- raise PaymentRequiredError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Optional[typing.Any]:
- """
- Retrieve a SIP trunk by ID.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The requested SIP trunk.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.sip_trunks.get(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/sip-trunks/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Delete a SIP trunk. This also removes the backing LiveKit inbound
- trunk, outbound trunk, and dispatch rule if they were provisioned
- by us. Phone numbers attached to this trunk are left in place but
- become non-functional until rebound to a new trunk.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.sip_trunks.delete(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/sip-trunks/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
-
-class AsyncSipTrunksClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> typing.Optional[typing.Any]:
- """
- List all SIP trunks in the caller's workspace.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The SIP trunks for the workspace.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.sip_trunks.list()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/sip-trunks",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def create(
- self, *, request: typing.Optional[typing.Any] = None, request_options: typing.Optional[RequestOptions] = None
- ) -> typing.Optional[typing.Any]:
- """
- Create a SIP trunk. For `kind=byoc` supply `sip_address` plus
- optional digest credentials and IP allowlist. For `kind=twilio`
- use `ImportPhoneNumber` with a `twilio` spec instead - trunk
- creation is handled automatically. Returns 402 when the workspace
- has reached the 20-trunk cap.
-
- Parameters
- ----------
- request : typing.Optional[typing.Any]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The created SIP trunk.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.sip_trunks.create(
- request={"key": "value"},
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/sip-trunks",
- method="POST",
- json=request,
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 402:
- raise PaymentRequiredError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def get(
- self, id: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> typing.Optional[typing.Any]:
- """
- Retrieve a SIP trunk by ID.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- typing.Optional[typing.Any]
- The requested SIP trunk.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.sip_trunks.get(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/sip-trunks/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Delete a SIP trunk. This also removes the backing LiveKit inbound
- trunk, outbound trunk, and dispatch rule if they were provisioned
- by us. Phone numbers attached to this trunk are left in place but
- become non-functional until rebound to a new trunk.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.sip_trunks.delete(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/sip-trunks/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
diff --git a/src/speechify/tts/tools/__init__.py b/src/speechify/tts/tools/__init__.py
deleted file mode 100644
index 3d29f5d..0000000
--- a/src/speechify/tts/tools/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from .types import CreateToolRequestConfig, UpdateToolRequestConfig
-
-__all__ = ["CreateToolRequestConfig", "UpdateToolRequestConfig"]
diff --git a/src/speechify/tts/tools/client.py b/src/speechify/tts/tools/client.py
deleted file mode 100644
index 56cbb77..0000000
--- a/src/speechify/tts/tools/client.py
+++ /dev/null
@@ -1,828 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from ...core.client_wrapper import SyncClientWrapper
-from ...core.request_options import RequestOptions
-from ..types.list_tools_response import ListToolsResponse
-from ...core.pydantic_utilities import parse_obj_as
-from ..errors.unauthorized_error import UnauthorizedError
-from json.decoder import JSONDecodeError
-from ...core.api_error import ApiError
-from ..types.tool_kind import ToolKind
-from .types.create_tool_request_config import CreateToolRequestConfig
-from ..types.tool import Tool
-from ...core.serialization import convert_and_respect_annotation_metadata
-from ..errors.bad_request_error import BadRequestError
-from ...core.jsonable_encoder import jsonable_encoder
-from ..errors.not_found_error import NotFoundError
-from .types.update_tool_request_config import UpdateToolRequestConfig
-from ...core.client_wrapper import AsyncClientWrapper
-
-# this is used as the default value for optional parameters
-OMIT = typing.cast(typing.Any, ...)
-
-
-class ToolsClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListToolsResponse:
- """
- List tools owned by the caller.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListToolsResponse
- A list of tools.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.tools.list()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/tools",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListToolsResponse,
- parse_obj_as(
- type_=ListToolsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def create(
- self,
- *,
- name: str,
- description: str,
- kind: ToolKind,
- config: CreateToolRequestConfig,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> Tool:
- """
- Create a tool. For webhook tools, the response includes the HMAC
- `webhook_secret` exactly once — store it immediately; subsequent
- reads return a masked placeholder.
-
- Parameters
- ----------
- name : str
-
- description : str
-
- kind : ToolKind
-
- config : CreateToolRequestConfig
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Tool
- The created tool.
-
- Examples
- --------
- from speechify import Speechify
- from speechify.tts import SystemToolConfig
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.tools.create(
- name="name",
- description="description",
- kind="system",
- config=SystemToolConfig(
- builtin="end_call",
- ),
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/tools",
- method="POST",
- json={
- "name": name,
- "description": description,
- "kind": kind,
- "config": convert_and_respect_annotation_metadata(
- object_=config, annotation=CreateToolRequestConfig, direction="write"
- ),
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Tool,
- parse_obj_as(
- type_=Tool, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Tool:
- """
- Retrieve a tool by ID. Webhook secrets are always masked here.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Tool
- The requested tool.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.tools.get(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tools/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Tool,
- parse_obj_as(
- type_=Tool, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Delete a tool. Agents that had it attached get a soft-detach.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.tools.delete(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tools/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def update(
- self,
- id: str,
- *,
- name: typing.Optional[str] = OMIT,
- description: typing.Optional[str] = OMIT,
- config: typing.Optional[UpdateToolRequestConfig] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> Tool:
- """
- Update a tool. Tool kind is immutable — create a new tool to change it.
-
- Parameters
- ----------
- id : str
-
- name : typing.Optional[str]
-
- description : typing.Optional[str]
-
- config : typing.Optional[UpdateToolRequestConfig]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Tool
- The updated tool.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.tools.update(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tools/{jsonable_encoder(id)}",
- method="PATCH",
- json={
- "name": name,
- "description": description,
- "config": convert_and_respect_annotation_metadata(
- object_=config, annotation=UpdateToolRequestConfig, direction="write"
- ),
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Tool,
- parse_obj_as(
- type_=Tool, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
-
-class AsyncToolsClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ListToolsResponse:
- """
- List tools owned by the caller.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- ListToolsResponse
- A list of tools.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.tools.list()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/tools",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- ListToolsResponse,
- parse_obj_as(
- type_=ListToolsResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def create(
- self,
- *,
- name: str,
- description: str,
- kind: ToolKind,
- config: CreateToolRequestConfig,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> Tool:
- """
- Create a tool. For webhook tools, the response includes the HMAC
- `webhook_secret` exactly once — store it immediately; subsequent
- reads return a masked placeholder.
-
- Parameters
- ----------
- name : str
-
- description : str
-
- kind : ToolKind
-
- config : CreateToolRequestConfig
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Tool
- The created tool.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
- from speechify.tts import SystemToolConfig
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.tools.create(
- name="name",
- description="description",
- kind="system",
- config=SystemToolConfig(
- builtin="end_call",
- ),
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/tools",
- method="POST",
- json={
- "name": name,
- "description": description,
- "kind": kind,
- "config": convert_and_respect_annotation_metadata(
- object_=config, annotation=CreateToolRequestConfig, direction="write"
- ),
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Tool,
- parse_obj_as(
- type_=Tool, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def get(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Tool:
- """
- Retrieve a tool by ID. Webhook secrets are always masked here.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Tool
- The requested tool.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.tools.get(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tools/{jsonable_encoder(id)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Tool,
- parse_obj_as(
- type_=Tool, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Delete a tool. Agents that had it attached get a soft-detach.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.tools.delete(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tools/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def update(
- self,
- id: str,
- *,
- name: typing.Optional[str] = OMIT,
- description: typing.Optional[str] = OMIT,
- config: typing.Optional[UpdateToolRequestConfig] = OMIT,
- request_options: typing.Optional[RequestOptions] = None,
- ) -> Tool:
- """
- Update a tool. Tool kind is immutable — create a new tool to change it.
-
- Parameters
- ----------
- id : str
-
- name : typing.Optional[str]
-
- description : typing.Optional[str]
-
- config : typing.Optional[UpdateToolRequestConfig]
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Tool
- The updated tool.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.tools.update(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tools/{jsonable_encoder(id)}",
- method="PATCH",
- json={
- "name": name,
- "description": description,
- "config": convert_and_respect_annotation_metadata(
- object_=config, annotation=UpdateToolRequestConfig, direction="write"
- ),
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Tool,
- parse_obj_as(
- type_=Tool, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
diff --git a/src/speechify/tts/tools/types/__init__.py b/src/speechify/tts/tools/types/__init__.py
deleted file mode 100644
index 5bc7f9e..0000000
--- a/src/speechify/tts/tools/types/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from .create_tool_request_config import CreateToolRequestConfig
-from .update_tool_request_config import UpdateToolRequestConfig
-
-__all__ = ["CreateToolRequestConfig", "UpdateToolRequestConfig"]
diff --git a/src/speechify/tts/tools/types/create_tool_request_config.py b/src/speechify/tts/tools/types/create_tool_request_config.py
deleted file mode 100644
index d1a85f1..0000000
--- a/src/speechify/tts/tools/types/create_tool_request_config.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from ...types.system_tool_config import SystemToolConfig
-from ...types.webhook_tool_config import WebhookToolConfig
-from ...types.client_tool_config import ClientToolConfig
-
-CreateToolRequestConfig = typing.Union[SystemToolConfig, WebhookToolConfig, ClientToolConfig]
diff --git a/src/speechify/tts/tools/types/update_tool_request_config.py b/src/speechify/tts/tools/types/update_tool_request_config.py
deleted file mode 100644
index b20f9b7..0000000
--- a/src/speechify/tts/tools/types/update_tool_request_config.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from ...types.system_tool_config import SystemToolConfig
-from ...types.webhook_tool_config import WebhookToolConfig
-from ...types.client_tool_config import ClientToolConfig
-
-UpdateToolRequestConfig = typing.Union[SystemToolConfig, WebhookToolConfig, ClientToolConfig]
diff --git a/src/speechify/tts/types/__init__.py b/src/speechify/tts/types/__init__.py
deleted file mode 100644
index accbecf..0000000
--- a/src/speechify/tts/types/__init__.py
+++ /dev/null
@@ -1,235 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from .access_token import AccessToken
-from .access_token_scope import AccessTokenScope
-from .access_token_token_type import AccessTokenTokenType
-from .agent import Agent
-from .agent_test import AgentTest
-from .agent_test_attachment import AgentTestAttachment
-from .agent_test_config import AgentTestConfig
-from .agent_test_folder import AgentTestFolder
-from .agent_test_run import AgentTestRun
-from .agent_test_with_last_run import AgentTestWithLastRun
-from .api_key import ApiKey
-from .batch_run_entry import BatchRunEntry
-from .client_tool_config import ClientToolConfig
-from .conversation import Conversation
-from .conversation_stats import ConversationStats
-from .conversation_status import ConversationStatus
-from .conversation_transport import ConversationTransport
-from .create_conversation_response import CreateConversationResponse
-from .create_voice_language import CreateVoiceLanguage
-from .create_voice_model import CreateVoiceModel
-from .create_voice_model_name import CreateVoiceModelName
-from .created_voice import CreatedVoice
-from .created_voice_gender import CreatedVoiceGender
-from .created_voice_type import CreatedVoiceType
-from .data_collection_field import DataCollectionField
-from .data_collection_field_type import DataCollectionFieldType
-from .delete_memories_by_caller_response import DeleteMemoriesByCallerResponse
-from .dynamic_variable import DynamicVariable
-from .dynamic_variable_type import DynamicVariableType
-from .evaluation import Evaluation
-from .evaluation_config import EvaluationConfig
-from .evaluation_criterion import EvaluationCriterion
-from .evaluation_kind import EvaluationKind
-from .evaluation_status import EvaluationStatus
-from .get_speech_options_request import GetSpeechOptionsRequest
-from .get_speech_response import GetSpeechResponse
-from .get_speech_response_audio_format import GetSpeechResponseAudioFormat
-from .get_stream_options_request import GetStreamOptionsRequest
-from .get_voice import GetVoice
-from .get_voice_gender import GetVoiceGender
-from .get_voice_language import GetVoiceLanguage
-from .get_voice_type import GetVoiceType
-from .get_voices_model import GetVoicesModel
-from .get_voices_model_name import GetVoicesModelName
-from .invite import Invite
-from .invite_preview import InvitePreview
-from .invites_list_response import InvitesListResponse
-from .knowledge_base import KnowledgeBase
-from .knowledge_base_chunk import KnowledgeBaseChunk
-from .knowledge_base_document import KnowledgeBaseDocument
-from .knowledge_base_document_status import KnowledgeBaseDocumentStatus
-from .knowledge_base_search_hit import KnowledgeBaseSearchHit
-from .list_agent_test_attachments_response import ListAgentTestAttachmentsResponse
-from .list_agent_test_folders_response import ListAgentTestFoldersResponse
-from .list_agent_test_runs_response import ListAgentTestRunsResponse
-from .list_agent_tests_response import ListAgentTestsResponse
-from .list_agents_response import ListAgentsResponse
-from .list_conversations_response import ListConversationsResponse
-from .list_dynamic_variables_response import ListDynamicVariablesResponse
-from .list_evaluations_response import ListEvaluationsResponse
-from .list_knowledge_base_chunks_response import ListKnowledgeBaseChunksResponse
-from .list_knowledge_base_documents_response import ListKnowledgeBaseDocumentsResponse
-from .list_knowledge_bases_response import ListKnowledgeBasesResponse
-from .list_memories_response import ListMemoriesResponse
-from .list_messages_response import ListMessagesResponse
-from .list_tests_response import ListTestsResponse
-from .list_tools_response import ListToolsResponse
-from .member import Member
-from .member_role import MemberRole
-from .members_list_response import MembersListResponse
-from .memory import Memory
-from .message import Message
-from .message_role import MessageRole
-from .mocking_strategy import MockingStrategy
-from .nested_chunk import NestedChunk
-from .no_match_behavior import NoMatchBehavior
-from .o_auth_error import OAuthError
-from .o_auth_error_error import OAuthErrorError
-from .parameter_check import ParameterCheck
-from .parameter_check_mode import ParameterCheckMode
-from .parameter_check_result import ParameterCheckResult
-from .run_agent_tests_response import RunAgentTestsResponse
-from .run_batch_response import RunBatchResponse
-from .scenario_config import ScenarioConfig
-from .scenario_result import ScenarioResult
-from .search_knowledge_bases_response import SearchKnowledgeBasesResponse
-from .simulation_config import SimulationConfig
-from .simulation_message import SimulationMessage
-from .simulation_message_role import SimulationMessageRole
-from .simulation_result import SimulationResult
-from .simulation_tool_call import SimulationToolCall
-from .speech_marks import SpeechMarks
-from .system_tool_config import SystemToolConfig
-from .system_tool_config_builtin import SystemToolConfigBuiltin
-from .system_variable_doc import SystemVariableDoc
-from .tenant import Tenant
-from .tenant_data_region import TenantDataRegion
-from .tenant_plan import TenantPlan
-from .tenants_list_response import TenantsListResponse
-from .test_run_result import TestRunResult
-from .test_run_status import TestRunStatus
-from .test_stats import TestStats
-from .test_stats_bucket import TestStatsBucket
-from .test_type import TestType
-from .tool import Tool
-from .tool_call_config import ToolCallConfig
-from .tool_call_result import ToolCallResult
-from .tool_config import ToolConfig
-from .tool_kind import ToolKind
-from .tool_mock import ToolMock
-from .tool_mock_config import ToolMockConfig
-from .tool_param import ToolParam
-from .tool_param_type import ToolParamType
-from .webhook_tool_config import WebhookToolConfig
-from .webhook_tool_config_method import WebhookToolConfigMethod
-
-__all__ = [
- "AccessToken",
- "AccessTokenScope",
- "AccessTokenTokenType",
- "Agent",
- "AgentTest",
- "AgentTestAttachment",
- "AgentTestConfig",
- "AgentTestFolder",
- "AgentTestRun",
- "AgentTestWithLastRun",
- "ApiKey",
- "BatchRunEntry",
- "ClientToolConfig",
- "Conversation",
- "ConversationStats",
- "ConversationStatus",
- "ConversationTransport",
- "CreateConversationResponse",
- "CreateVoiceLanguage",
- "CreateVoiceModel",
- "CreateVoiceModelName",
- "CreatedVoice",
- "CreatedVoiceGender",
- "CreatedVoiceType",
- "DataCollectionField",
- "DataCollectionFieldType",
- "DeleteMemoriesByCallerResponse",
- "DynamicVariable",
- "DynamicVariableType",
- "Evaluation",
- "EvaluationConfig",
- "EvaluationCriterion",
- "EvaluationKind",
- "EvaluationStatus",
- "GetSpeechOptionsRequest",
- "GetSpeechResponse",
- "GetSpeechResponseAudioFormat",
- "GetStreamOptionsRequest",
- "GetVoice",
- "GetVoiceGender",
- "GetVoiceLanguage",
- "GetVoiceType",
- "GetVoicesModel",
- "GetVoicesModelName",
- "Invite",
- "InvitePreview",
- "InvitesListResponse",
- "KnowledgeBase",
- "KnowledgeBaseChunk",
- "KnowledgeBaseDocument",
- "KnowledgeBaseDocumentStatus",
- "KnowledgeBaseSearchHit",
- "ListAgentTestAttachmentsResponse",
- "ListAgentTestFoldersResponse",
- "ListAgentTestRunsResponse",
- "ListAgentTestsResponse",
- "ListAgentsResponse",
- "ListConversationsResponse",
- "ListDynamicVariablesResponse",
- "ListEvaluationsResponse",
- "ListKnowledgeBaseChunksResponse",
- "ListKnowledgeBaseDocumentsResponse",
- "ListKnowledgeBasesResponse",
- "ListMemoriesResponse",
- "ListMessagesResponse",
- "ListTestsResponse",
- "ListToolsResponse",
- "Member",
- "MemberRole",
- "MembersListResponse",
- "Memory",
- "Message",
- "MessageRole",
- "MockingStrategy",
- "NestedChunk",
- "NoMatchBehavior",
- "OAuthError",
- "OAuthErrorError",
- "ParameterCheck",
- "ParameterCheckMode",
- "ParameterCheckResult",
- "RunAgentTestsResponse",
- "RunBatchResponse",
- "ScenarioConfig",
- "ScenarioResult",
- "SearchKnowledgeBasesResponse",
- "SimulationConfig",
- "SimulationMessage",
- "SimulationMessageRole",
- "SimulationResult",
- "SimulationToolCall",
- "SpeechMarks",
- "SystemToolConfig",
- "SystemToolConfigBuiltin",
- "SystemVariableDoc",
- "Tenant",
- "TenantDataRegion",
- "TenantPlan",
- "TenantsListResponse",
- "TestRunResult",
- "TestRunStatus",
- "TestStats",
- "TestStatsBucket",
- "TestType",
- "Tool",
- "ToolCallConfig",
- "ToolCallResult",
- "ToolConfig",
- "ToolKind",
- "ToolMock",
- "ToolMockConfig",
- "ToolParam",
- "ToolParamType",
- "WebhookToolConfig",
- "WebhookToolConfigMethod",
-]
diff --git a/src/speechify/tts/types/access_token.py b/src/speechify/tts/types/access_token.py
deleted file mode 100644
index 52dbb9d..0000000
--- a/src/speechify/tts/types/access_token.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-import pydantic
-from .access_token_scope import AccessTokenScope
-from .access_token_token_type import AccessTokenTokenType
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class AccessToken(UniversalBaseModel):
- access_token: typing.Optional[str] = None
- expires_in: typing.Optional[int] = pydantic.Field(default=None)
- """
- Expiration time, in seconds from the issue time
- """
-
- scope: typing.Optional[AccessTokenScope] = pydantic.Field(default=None)
- """
- The scope, or a space-delimited list of scopes the token is issued for
- """
-
- token_type: typing.Optional[AccessTokenTokenType] = pydantic.Field(default=None)
- """
- Token type
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/access_token_scope.py b/src/speechify/tts/types/access_token_scope.py
deleted file mode 100644
index 73cae3b..0000000
--- a/src/speechify/tts/types/access_token_scope.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-AccessTokenScope = typing.Union[
- typing.Literal[
- "audio:speech", "audio:stream", "audio:all", "voices:read", "voices:create", "voices:delete", "voices:all"
- ],
- typing.Any,
-]
diff --git a/src/speechify/tts/types/access_token_token_type.py b/src/speechify/tts/types/access_token_token_type.py
deleted file mode 100644
index 065f512..0000000
--- a/src/speechify/tts/types/access_token_token_type.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-AccessTokenTokenType = typing.Union[typing.Literal["bearer"], typing.Any]
diff --git a/src/speechify/tts/types/agent.py b/src/speechify/tts/types/agent.py
deleted file mode 100644
index 13a28c4..0000000
--- a/src/speechify/tts/types/agent.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-import pydantic
-import datetime as dt
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class Agent(UniversalBaseModel):
- id: str
- name: str
- slug: str
- prompt: typing.Optional[str] = None
- first_message: typing.Optional[str] = None
- language: str = pydantic.Field()
- """
- ISO 639-1 code, e.g. 'en'.
- """
-
- llm_model: str = pydantic.Field()
- """
- Chat model slug. Leave empty to use the Speechify default.
- """
-
- voice_id: str = pydantic.Field()
- """
- Speechify voice slug.
- """
-
- temperature: float
- config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
- """
- Free-form agent config JSON (evaluation_config is read via its own endpoint).
- """
-
- is_public: bool = pydantic.Field()
- """
- When true, the `` web component can start a
- session against this agent without an API key, subject to
- the `allowed_origins` allowlist. When false (default), only
- authenticated callers can start sessions.
- """
-
- allowed_origins: typing.List[str] = pydantic.Field()
- """
- Exact `Origin` header values (e.g. `https://example.com`)
- that are allowed to start public sessions. Empty array
- with `is_public = true` means any origin is accepted —
- intended for open demos. No subdomain wildcards.
- """
-
- hostname_allowlist: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
- """
- Optional per-agent hostname allowlist enforced at
- session-creation time. When set and non-empty, the
- `Origin` header's hostname must be an exact member.
- Bare hostnames only — no scheme, port, or path. Up to
- 10 entries. Omit (null) or leave empty for no
- enforcement (public agents accept any hostname).
- """
-
- memory_enabled: bool = pydantic.Field()
- """
- When true, the post-call extractor writes durable facts about
- each caller; at conversation-start the retriever injects the
- top matches into the system prompt via the `{{memory}}`
- template variable. Defaults to false.
- """
-
- memory_retention_days: int = pydantic.Field()
- """
- Maximum age (in days) of memories kept and surfaced to the
- retriever. 0 disables the cap. Defaults to 90.
- """
-
- created_at: dt.datetime
- updated_at: dt.datetime
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/agent_test.py b/src/speechify/tts/types/agent_test.py
deleted file mode 100644
index 9b7cf6c..0000000
--- a/src/speechify/tts/types/agent_test.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from .test_type import TestType
-from .agent_test_config import AgentTestConfig
-import pydantic
-import typing
-from .tool_mock_config import ToolMockConfig
-import datetime as dt
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class AgentTest(UniversalBaseModel):
- """
- A configured test against a voice agent. `config` is a
- type-specific document - see `ScenarioConfig`, `ToolCallConfig`,
- and `SimulationConfig` for the per-type shapes (discriminated by `type`).
- """
-
- id: str
- agent_id: str
- name: str
- description: str
- type: TestType
- config: AgentTestConfig = pydantic.Field()
- """
- Type-specific configuration document.
- """
-
- tool_mock_config: typing.Optional[ToolMockConfig] = pydantic.Field(default=None)
- """
- Optional tool-mocking config applied during runs of this test.
- """
-
- variables: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
- """
- Per-test dynamic-variable overrides. Keys substitute `{{key}}`
- placeholders inside the test config at run-start. Unknown keys
- render as empty string, matching session dispatch behaviour.
- """
-
- folder_id: typing.Optional[str] = pydantic.Field(default=None)
- """
- Folder the test belongs to; null = root (unfiled).
- """
-
- created_at: dt.datetime
- updated_at: dt.datetime
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/agent_test_attachment.py b/src/speechify/tts/types/agent_test_attachment.py
deleted file mode 100644
index 3a1f30f..0000000
--- a/src/speechify/tts/types/agent_test_attachment.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import datetime as dt
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import typing
-import pydantic
-
-
-class AgentTestAttachment(UniversalBaseModel):
- """
- One (test, agent) pair. Poll the `attached_agent_ids` field on `AgentTestWithLastRun` or hit `/v1/tests/{id}/attachments` for the authoritative set.
- """
-
- test_id: str
- agent_id: str
- created_at: dt.datetime
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/agent_test_config.py b/src/speechify/tts/types/agent_test_config.py
deleted file mode 100644
index d0ce190..0000000
--- a/src/speechify/tts/types/agent_test_config.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from .scenario_config import ScenarioConfig
-from .tool_call_config import ToolCallConfig
-from .simulation_config import SimulationConfig
-
-AgentTestConfig = typing.Union[ScenarioConfig, ToolCallConfig, SimulationConfig]
diff --git a/src/speechify/tts/types/agent_test_folder.py b/src/speechify/tts/types/agent_test_folder.py
deleted file mode 100644
index 88cc31d..0000000
--- a/src/speechify/tts/types/agent_test_folder.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-import datetime as dt
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class AgentTestFolder(UniversalBaseModel):
- """
- One organisational node in the per-owner tests tree.
- """
-
- id: str
- parent_folder_id: typing.Optional[str] = None
- name: str
- created_at: dt.datetime
- updated_at: dt.datetime
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/agent_test_run.py b/src/speechify/tts/types/agent_test_run.py
deleted file mode 100644
index 3f51754..0000000
--- a/src/speechify/tts/types/agent_test_run.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from .test_run_status import TestRunStatus
-import typing
-import datetime as dt
-from .test_run_result import TestRunResult
-import pydantic
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class AgentTestRun(UniversalBaseModel):
- """
- One execution of a test. `result` is populated when `status`
- reaches a terminal state (`passed`, `failed`, or `error`).
- See `TestRunResult` for the shape.
- """
-
- id: str
- test_id: str
- agent_id: str
- status: TestRunStatus
- started_at: typing.Optional[dt.datetime] = None
- completed_at: typing.Optional[dt.datetime] = None
- result: typing.Optional[TestRunResult] = pydantic.Field(default=None)
- """
- Populated on terminal status only.
- """
-
- error: typing.Optional[str] = pydantic.Field(default=None)
- """
- Human-readable error message when status is `error`.
- """
-
- created_at: dt.datetime
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/agent_test_with_last_run.py b/src/speechify/tts/types/agent_test_with_last_run.py
deleted file mode 100644
index cb22c0b..0000000
--- a/src/speechify/tts/types/agent_test_with_last_run.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from .agent_test import AgentTest
-import typing
-from .agent_test_run import AgentTestRun
-import pydantic
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class AgentTestWithLastRun(AgentTest):
- """
- List-view projection of a test that includes the most recent run
- so the console can display pass/fail badges without an extra
- round-trip. On the global `/v1/tests` surface, also carries
- `attached_agent_ids` so the row can render agent chips without a
- follow-up request.
- """
-
- last_run: typing.Optional[AgentTestRun] = pydantic.Field(default=None)
- """
- The most recent run, or null if the test has never been run.
- """
-
- attached_agent_ids: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
- """
- Every agent this test runs against. Always includes the owner agent.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/api_key.py b/src/speechify/tts/types/api_key.py
deleted file mode 100644
index ce1b612..0000000
--- a/src/speechify/tts/types/api_key.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-import pydantic
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class ApiKey(UniversalBaseModel):
- api_key: typing.Optional[str] = pydantic.Field(default=None)
- """
- API key
- """
-
- created_at: typing.Optional[int] = pydantic.Field(default=None)
- """
- Creation time of the key
- """
-
- id: typing.Optional[int] = pydantic.Field(default=None)
- """
- ID of the key
- """
-
- name: typing.Optional[str] = pydantic.Field(default=None)
- """
- Name of the key
- """
-
- updated_at: typing.Optional[int] = pydantic.Field(default=None)
- """
- Last updated time of the key
- """
-
- user_id: typing.Optional[str] = pydantic.Field(default=None)
- """
- User ID to whom the key belongs
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/batch_run_entry.py b/src/speechify/tts/types/batch_run_entry.py
deleted file mode 100644
index 7ba49b3..0000000
--- a/src/speechify/tts/types/batch_run_entry.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class BatchRunEntry(UniversalBaseModel):
- """
- One entry in a batch-run request. Omit `agent_id` to fan out to
- every agent the test is attached to.
- """
-
- test_id: str
- agent_id: typing.Optional[str] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/client_tool_config.py b/src/speechify/tts/types/client_tool_config.py
deleted file mode 100644
index 5966aaa..0000000
--- a/src/speechify/tts/types/client_tool_config.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .tool_param import ToolParam
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ClientToolConfig(UniversalBaseModel):
- """
- Config shape for `kind=client`. Execution happens in the caller's browser / SDK.
- """
-
- params: typing.Optional[typing.List[ToolParam]] = None
- timeout_ms: typing.Optional[int] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/conversation.py b/src/speechify/tts/types/conversation.py
deleted file mode 100644
index e198694..0000000
--- a/src/speechify/tts/types/conversation.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .conversation_status import ConversationStatus
-from .conversation_transport import ConversationTransport
-import datetime as dt
-import pydantic
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class Conversation(UniversalBaseModel):
- id: str
- agent_id: str
- room_name: str
- room_sid: typing.Optional[str] = None
- status: ConversationStatus
- transport: ConversationTransport
- started_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
- """
- Set when the first user participant joins the realtime
- voice session. Null between CreateConversation and the
- participant-joined event, and stays null if no user ever
- joins.
- """
-
- ended_at: typing.Optional[dt.datetime] = None
- duration_ms: typing.Optional[int] = None
- cost_cents: typing.Optional[int] = None
- recording_url: typing.Optional[str] = None
- metadata: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/conversation_stats.py b/src/speechify/tts/types/conversation_stats.py
deleted file mode 100644
index 011243f..0000000
--- a/src/speechify/tts/types/conversation_stats.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ConversationStats(UniversalBaseModel):
- """
- Counts + averages over the caller's conversations matching the supplied filters. AVG fields are null when no rows match the FILTER predicate.
- """
-
- total: int
- completed: int
- failed: int
- active: int
- pending: int
- avg_duration_ms: typing.Optional[float] = None
- avg_cost_cents: typing.Optional[float] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/conversation_status.py b/src/speechify/tts/types/conversation_status.py
deleted file mode 100644
index 7b121bf..0000000
--- a/src/speechify/tts/types/conversation_status.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-ConversationStatus = typing.Union[typing.Literal["pending", "active", "completed", "failed"], typing.Any]
diff --git a/src/speechify/tts/types/conversation_transport.py b/src/speechify/tts/types/conversation_transport.py
deleted file mode 100644
index 4451eb9..0000000
--- a/src/speechify/tts/types/conversation_transport.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-ConversationTransport = typing.Union[typing.Literal["web", "sip"], typing.Any]
diff --git a/src/speechify/tts/types/create_conversation_response.py b/src/speechify/tts/types/create_conversation_response.py
deleted file mode 100644
index cc53806..0000000
--- a/src/speechify/tts/types/create_conversation_response.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from .conversation import Conversation
-import pydantic
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import typing
-
-
-class CreateConversationResponse(UniversalBaseModel):
- """
- Returned when a conversation is created. The `token` + `url`
- let the caller connect its browser/SDK directly to the
- realtime voice session — the agent that answers is dispatched
- server-side.
- """
-
- conversation: Conversation
- room: str
- token: str = pydantic.Field()
- """
- Short-lived realtime session access token (JWT).
- """
-
- url: str = pydantic.Field()
- """
- Realtime session wss:// URL to connect to.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/create_voice_model_name.py b/src/speechify/tts/types/create_voice_model_name.py
deleted file mode 100644
index 34c21b3..0000000
--- a/src/speechify/tts/types/create_voice_model_name.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-CreateVoiceModelName = typing.Union[
- typing.Literal["simba-base", "simba-english", "simba-multilingual", "simba-turbo", "simba-3.0"], typing.Any
-]
diff --git a/src/speechify/tts/types/data_collection_field.py b/src/speechify/tts/types/data_collection_field.py
deleted file mode 100644
index 1f55f6b..0000000
--- a/src/speechify/tts/types/data_collection_field.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from .data_collection_field_type import DataCollectionFieldType
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import typing
-import pydantic
-
-
-class DataCollectionField(UniversalBaseModel):
- """
- A structured value the post-call evaluator should extract from the
- transcript. `int` is distinct from `number` so downstream consumers
- receive whole integers without a synthetic decimal.
- """
-
- key: str
- description: str
- type: DataCollectionFieldType
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/data_collection_field_type.py b/src/speechify/tts/types/data_collection_field_type.py
deleted file mode 100644
index b9a1a96..0000000
--- a/src/speechify/tts/types/data_collection_field_type.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DataCollectionFieldType = typing.Union[typing.Literal["string", "int", "number", "boolean"], typing.Any]
diff --git a/src/speechify/tts/types/delete_memories_by_caller_response.py b/src/speechify/tts/types/delete_memories_by_caller_response.py
deleted file mode 100644
index f7fdf5b..0000000
--- a/src/speechify/tts/types/delete_memories_by_caller_response.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import typing
-
-
-class DeleteMemoriesByCallerResponse(UniversalBaseModel):
- deleted: int = pydantic.Field()
- """
- Number of memories soft-deleted.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/dynamic_variable.py b/src/speechify/tts/types/dynamic_variable.py
deleted file mode 100644
index aab728b..0000000
--- a/src/speechify/tts/types/dynamic_variable.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-from .dynamic_variable_type import DynamicVariableType
-import typing
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class DynamicVariable(UniversalBaseModel):
- """
- One customer-scope variable definition on an agent. Referenced in
- prompts, first messages, and webhook tool configs via `{{key}}` or
- `{{key|json}}`. Missing variables render as empty string at dispatch
- time - a typo never breaks a session.
- """
-
- key: str = pydantic.Field()
- """
- Variable name. Must match `[a-zA-Z0-9_]+`. The `system__` prefix
- is reserved for platform-populated variables and will be rejected.
- """
-
- type: DynamicVariableType
- default: typing.Optional[typing.Optional[typing.Any]] = pydantic.Field(default=None)
- """
- Optional default value used when no per-session override is
- supplied. Must conform to the declared `type`.
- """
-
- description: typing.Optional[str] = pydantic.Field(default=None)
- """
- Human-readable note shown in the console variable editor.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/dynamic_variable_type.py b/src/speechify/tts/types/dynamic_variable_type.py
deleted file mode 100644
index d12f3f8..0000000
--- a/src/speechify/tts/types/dynamic_variable_type.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-DynamicVariableType = typing.Union[typing.Literal["string", "number", "boolean", "json"], typing.Any]
diff --git a/src/speechify/tts/types/evaluation.py b/src/speechify/tts/types/evaluation.py
deleted file mode 100644
index 06414f1..0000000
--- a/src/speechify/tts/types/evaluation.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from .evaluation_kind import EvaluationKind
-import typing
-from .evaluation_status import EvaluationStatus
-import pydantic
-import datetime as dt
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class Evaluation(UniversalBaseModel):
- """
- Three flavours coexist, discriminated by `kind`:
- - `criterion` rows carry `status` + `passed` + `score` + `rationale` for one criterion
- - `summary` row carries overall sentiment + rationale in `rationale`
- - `data` row carries the structured data-collection payload in `data`
-
- `status` is the canonical three-state result. `passed` is a
- derived boolean kept for backwards compatibility with earlier
- webhook consumers: success→true, failure→false, unknown→null.
- """
-
- id: str
- conversation_id: str
- kind: EvaluationKind
- criterion_id: typing.Optional[str] = None
- name: str
- status: typing.Optional[EvaluationStatus] = pydantic.Field(default=None)
- """
- Three-state criterion result. `unknown` means the criterion did not apply to this call.
- """
-
- passed: typing.Optional[bool] = None
- score: typing.Optional[float] = None
- rationale: str
- data: typing.Optional[typing.Optional[typing.Any]] = pydantic.Field(default=None)
- """
- Structured data-collection payload (present only on `kind=data` rows).
- """
-
- created_at: dt.datetime
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/evaluation_config.py b/src/speechify/tts/types/evaluation_config.py
deleted file mode 100644
index cc757ed..0000000
--- a/src/speechify/tts/types/evaluation_config.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .evaluation_criterion import EvaluationCriterion
-from .data_collection_field import DataCollectionField
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class EvaluationConfig(UniversalBaseModel):
- criteria: typing.List[EvaluationCriterion]
- data_collection: typing.List[DataCollectionField]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/evaluation_criterion.py b/src/speechify/tts/types/evaluation_criterion.py
deleted file mode 100644
index 235443b..0000000
--- a/src/speechify/tts/types/evaluation_criterion.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import typing
-import pydantic
-
-
-class EvaluationCriterion(UniversalBaseModel):
- """
- One LLM-scored assertion about the call ("Did the agent confirm the customer's name?").
- """
-
- id: str
- name: str
- description: str
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/evaluation_kind.py b/src/speechify/tts/types/evaluation_kind.py
deleted file mode 100644
index 8c1feac..0000000
--- a/src/speechify/tts/types/evaluation_kind.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-EvaluationKind = typing.Union[typing.Literal["criterion", "summary", "data"], typing.Any]
diff --git a/src/speechify/tts/types/evaluation_status.py b/src/speechify/tts/types/evaluation_status.py
deleted file mode 100644
index 9af14a4..0000000
--- a/src/speechify/tts/types/evaluation_status.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-EvaluationStatus = typing.Union[typing.Literal["success", "failure", "unknown"], typing.Any]
diff --git a/src/speechify/tts/types/get_voices_model_name.py b/src/speechify/tts/types/get_voices_model_name.py
deleted file mode 100644
index 121de6e..0000000
--- a/src/speechify/tts/types/get_voices_model_name.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-GetVoicesModelName = typing.Union[
- typing.Literal["simba-base", "simba-english", "simba-multilingual", "simba-turbo"], typing.Any
-]
diff --git a/src/speechify/tts/types/invite.py b/src/speechify/tts/types/invite.py
deleted file mode 100644
index 3314199..0000000
--- a/src/speechify/tts/types/invite.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-import datetime as dt
-import typing
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class Invite(UniversalBaseModel):
- """
- A pending or historical workspace invite.
- """
-
- id: str = pydantic.Field()
- """
- Opaque invite ID.
- """
-
- email: str = pydantic.Field()
- """
- Invitee email.
- """
-
- invited_by: str = pydantic.Field()
- """
- Firebase UID of the member who created the invite.
- """
-
- created_at: dt.datetime
- expires_at: dt.datetime
- accepted_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
- """
- Populated once the invite has been accepted.
- """
-
- revoked_at: typing.Optional[dt.datetime] = pydantic.Field(default=None)
- """
- Populated once the invite has been revoked.
- """
-
- token: typing.Optional[str] = pydantic.Field(default=None)
- """
- Invite token. Returned ONLY on the create-invite response;
- subsequent list calls redact it. Use the token to build the
- `/join/{token}` join URL.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/invite_preview.py b/src/speechify/tts/types/invite_preview.py
deleted file mode 100644
index 0a9d2ca..0000000
--- a/src/speechify/tts/types/invite_preview.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-import typing
-import datetime as dt
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class InvitePreview(UniversalBaseModel):
- """
- Unauthenticated preview of a workspace invite. Surfaces only what
- the recipient needs to decide whether to accept (workspace name,
- invited address, inviter, expiry). Billing, plan, data region,
- and invite token are deliberately omitted.
- """
-
- tenant_id: str = pydantic.Field()
- """
- Opaque workspace id. Safe to echo back on the accept call.
- """
-
- tenant_name: str = pydantic.Field()
- """
- Workspace display name.
- """
-
- invited_email: str = pydantic.Field()
- """
- The email address the inviter typed when creating the invite.
- """
-
- invited_by_email: typing.Optional[str] = pydantic.Field(default=None)
- """
- Firebase email of the member who created the invite. May be
- absent if the Firebase profile lookup failed transiently —
- clients should still render the preview in that case.
- """
-
- invited_by_display_name: typing.Optional[str] = pydantic.Field(default=None)
- """
- Firebase display name of the member who created the invite.
- """
-
- expires_at: dt.datetime
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/invites_list_response.py b/src/speechify/tts/types/invites_list_response.py
deleted file mode 100644
index 640fcc9..0000000
--- a/src/speechify/tts/types/invites_list_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .invite import Invite
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class InvitesListResponse(UniversalBaseModel):
- invites: typing.List[Invite]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/knowledge_base.py b/src/speechify/tts/types/knowledge_base.py
deleted file mode 100644
index 55add05..0000000
--- a/src/speechify/tts/types/knowledge_base.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-import datetime as dt
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import typing
-
-
-class KnowledgeBase(UniversalBaseModel):
- """
- A bundle of documents that can be attached to one or more voice
- agents. Chunks across every document in the knowledge base are
- embedded and searched together.
- """
-
- id: str
- name: str = pydantic.Field()
- """
- Human-readable label, shown in the console.
- """
-
- description: str = pydantic.Field()
- """
- Optional description.
- """
-
- document_count: int = pydantic.Field()
- """
- Number of ingested documents.
- """
-
- created_at: dt.datetime
- updated_at: dt.datetime
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/knowledge_base_chunk.py b/src/speechify/tts/types/knowledge_base_chunk.py
deleted file mode 100644
index c0e2081..0000000
--- a/src/speechify/tts/types/knowledge_base_chunk.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import typing
-import pydantic
-
-
-class KnowledgeBaseChunk(UniversalBaseModel):
- id: str
- document_id: str
- kb_id: str
- chunk_index: int
- content: str
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/knowledge_base_document.py b/src/speechify/tts/types/knowledge_base_document.py
deleted file mode 100644
index bcf1ae3..0000000
--- a/src/speechify/tts/types/knowledge_base_document.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from .knowledge_base_document_status import KnowledgeBaseDocumentStatus
-import typing
-import pydantic
-import datetime as dt
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class KnowledgeBaseDocument(UniversalBaseModel):
- id: str
- kb_id: str
- filename: str
- content_type: str
- byte_size: int
- char_count: int
- chunk_count: int
- status: KnowledgeBaseDocumentStatus
- error: typing.Optional[str] = pydantic.Field(default=None)
- """
- Populated when status is failed.
- """
-
- created_at: dt.datetime
- updated_at: dt.datetime
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/knowledge_base_document_status.py b/src/speechify/tts/types/knowledge_base_document_status.py
deleted file mode 100644
index 35fb962..0000000
--- a/src/speechify/tts/types/knowledge_base_document_status.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-KnowledgeBaseDocumentStatus = typing.Union[typing.Literal["embedding", "ready", "failed"], typing.Any]
diff --git a/src/speechify/tts/types/knowledge_base_search_hit.py b/src/speechify/tts/types/knowledge_base_search_hit.py
deleted file mode 100644
index 4422827..0000000
--- a/src/speechify/tts/types/knowledge_base_search_hit.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import typing
-
-
-class KnowledgeBaseSearchHit(UniversalBaseModel):
- chunk_id: str
- document_id: str
- kb_id: str
- filename: str
- chunk_index: int
- content: str
- score: float = pydantic.Field()
- """
- Cosine similarity (higher = more relevant).
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_agent_test_attachments_response.py b/src/speechify/tts/types/list_agent_test_attachments_response.py
deleted file mode 100644
index 0f4287a..0000000
--- a/src/speechify/tts/types/list_agent_test_attachments_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .agent_test_attachment import AgentTestAttachment
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ListAgentTestAttachmentsResponse(UniversalBaseModel):
- attachments: typing.List[AgentTestAttachment]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_agent_test_folders_response.py b/src/speechify/tts/types/list_agent_test_folders_response.py
deleted file mode 100644
index 553d728..0000000
--- a/src/speechify/tts/types/list_agent_test_folders_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .agent_test_folder import AgentTestFolder
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ListAgentTestFoldersResponse(UniversalBaseModel):
- folders: typing.List[AgentTestFolder]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_agent_test_runs_response.py b/src/speechify/tts/types/list_agent_test_runs_response.py
deleted file mode 100644
index 27c484b..0000000
--- a/src/speechify/tts/types/list_agent_test_runs_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .agent_test_run import AgentTestRun
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ListAgentTestRunsResponse(UniversalBaseModel):
- runs: typing.List[AgentTestRun]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_agent_tests_response.py b/src/speechify/tts/types/list_agent_tests_response.py
deleted file mode 100644
index 41e6bdd..0000000
--- a/src/speechify/tts/types/list_agent_tests_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .agent_test_with_last_run import AgentTestWithLastRun
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ListAgentTestsResponse(UniversalBaseModel):
- tests: typing.List[AgentTestWithLastRun]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_agents_response.py b/src/speechify/tts/types/list_agents_response.py
deleted file mode 100644
index 757f14d..0000000
--- a/src/speechify/tts/types/list_agents_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .agent import Agent
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ListAgentsResponse(UniversalBaseModel):
- agents: typing.List[Agent]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_conversations_response.py b/src/speechify/tts/types/list_conversations_response.py
deleted file mode 100644
index 79c0d2a..0000000
--- a/src/speechify/tts/types/list_conversations_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .conversation import Conversation
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ListConversationsResponse(UniversalBaseModel):
- conversations: typing.List[Conversation]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_dynamic_variables_response.py b/src/speechify/tts/types/list_dynamic_variables_response.py
deleted file mode 100644
index 2cf72f8..0000000
--- a/src/speechify/tts/types/list_dynamic_variables_response.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .dynamic_variable import DynamicVariable
-import pydantic
-from .system_variable_doc import SystemVariableDoc
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class ListDynamicVariablesResponse(UniversalBaseModel):
- """
- Response for `GET /v1/agents/{id}/variables`. Returns both the
- customer-scope variable catalogue and the read-only `system__*`
- catalogue so the editor UI has a single source of truth.
- """
-
- variables: typing.List[DynamicVariable] = pydantic.Field()
- """
- Customer-defined variables for this agent.
- """
-
- system_variables: typing.List[SystemVariableDoc] = pydantic.Field()
- """
- Platform-populated `system__*` variables, provided for
- reference. This list is the same for every agent.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_evaluations_response.py b/src/speechify/tts/types/list_evaluations_response.py
deleted file mode 100644
index 79d9b91..0000000
--- a/src/speechify/tts/types/list_evaluations_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .evaluation import Evaluation
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ListEvaluationsResponse(UniversalBaseModel):
- evaluations: typing.List[Evaluation]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_knowledge_base_chunks_response.py b/src/speechify/tts/types/list_knowledge_base_chunks_response.py
deleted file mode 100644
index 9324636..0000000
--- a/src/speechify/tts/types/list_knowledge_base_chunks_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .knowledge_base_chunk import KnowledgeBaseChunk
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ListKnowledgeBaseChunksResponse(UniversalBaseModel):
- chunks: typing.List[KnowledgeBaseChunk]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_knowledge_base_documents_response.py b/src/speechify/tts/types/list_knowledge_base_documents_response.py
deleted file mode 100644
index 15d69ed..0000000
--- a/src/speechify/tts/types/list_knowledge_base_documents_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .knowledge_base_document import KnowledgeBaseDocument
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ListKnowledgeBaseDocumentsResponse(UniversalBaseModel):
- documents: typing.List[KnowledgeBaseDocument]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_knowledge_bases_response.py b/src/speechify/tts/types/list_knowledge_bases_response.py
deleted file mode 100644
index acb38d7..0000000
--- a/src/speechify/tts/types/list_knowledge_bases_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .knowledge_base import KnowledgeBase
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ListKnowledgeBasesResponse(UniversalBaseModel):
- knowledge_bases: typing.List[KnowledgeBase]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_memories_response.py b/src/speechify/tts/types/list_memories_response.py
deleted file mode 100644
index 79b426b..0000000
--- a/src/speechify/tts/types/list_memories_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .memory import Memory
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ListMemoriesResponse(UniversalBaseModel):
- memories: typing.List[Memory]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_messages_response.py b/src/speechify/tts/types/list_messages_response.py
deleted file mode 100644
index 1a71747..0000000
--- a/src/speechify/tts/types/list_messages_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .message import Message
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ListMessagesResponse(UniversalBaseModel):
- messages: typing.List[Message]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_tests_response.py b/src/speechify/tts/types/list_tests_response.py
deleted file mode 100644
index 144048b..0000000
--- a/src/speechify/tts/types/list_tests_response.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .agent_test_with_last_run import AgentTestWithLastRun
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ListTestsResponse(UniversalBaseModel):
- """
- Workspace-wide paginated list of tests. `next_cursor` is the opaque
- page cursor; omit on the first call, then pass through to get the
- next page until the field is absent.
- """
-
- tests: typing.List[AgentTestWithLastRun]
- next_cursor: typing.Optional[str] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/list_tools_response.py b/src/speechify/tts/types/list_tools_response.py
deleted file mode 100644
index bb7bb05..0000000
--- a/src/speechify/tts/types/list_tools_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .tool import Tool
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ListToolsResponse(UniversalBaseModel):
- tools: typing.List[Tool]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/member.py b/src/speechify/tts/types/member.py
deleted file mode 100644
index 158f541..0000000
--- a/src/speechify/tts/types/member.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-import typing
-from .member_role import MemberRole
-import datetime as dt
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class Member(UniversalBaseModel):
- """
- A member of a workspace (joined from `tenant_users` + Firebase profile).
- """
-
- user_uid: str = pydantic.Field()
- """
- Firebase user ID.
- """
-
- email: typing.Optional[str] = pydantic.Field(default=None)
- """
- Member's email from Firebase. Empty when the account has been deleted.
- """
-
- display_name: typing.Optional[str] = pydantic.Field(default=None)
- """
- Member's display name from Firebase.
- """
-
- role: MemberRole
- created_at: dt.datetime = pydantic.Field()
- """
- When the user joined the workspace.
- """
-
- is_self: bool = pydantic.Field()
- """
- True when this row is the authenticated caller.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/member_role.py b/src/speechify/tts/types/member_role.py
deleted file mode 100644
index 13def0f..0000000
--- a/src/speechify/tts/types/member_role.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-MemberRole = typing.Union[typing.Literal["owner", "admin", "member"], typing.Any]
diff --git a/src/speechify/tts/types/members_list_response.py b/src/speechify/tts/types/members_list_response.py
deleted file mode 100644
index 819d86d..0000000
--- a/src/speechify/tts/types/members_list_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .member import Member
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class MembersListResponse(UniversalBaseModel):
- members: typing.List[Member]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/memory.py b/src/speechify/tts/types/memory.py
deleted file mode 100644
index 373c863..0000000
--- a/src/speechify/tts/types/memory.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-import typing
-import datetime as dt
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class Memory(UniversalBaseModel):
- """
- One salient fact extracted post-call about a specific caller on
- a specific agent. Retrieved at the next conversation-start for
- the same caller and injected into the agent's system prompt via
- the `{{memory}}` template variable.
- """
-
- id: str
- agent_id: str
- caller_identity: str = pydantic.Field()
- """
- Stable caller key (LiveKit participant identity) the memory is scoped to.
- """
-
- fact: str = pydantic.Field()
- """
- Short third-person statement about the caller.
- """
-
- source_conversation_id: typing.Optional[str] = pydantic.Field(default=None)
- """
- Conversation the memory was extracted from (may be empty if the source was deleted).
- """
-
- confidence: float = pydantic.Field()
- """
- LLM self-reported 0-1 confidence in the fact's durability and relevance.
- """
-
- score: typing.Optional[float] = pydantic.Field(default=None)
- """
- Populated only on retrieval hits — recency-weighted cosine similarity.
- """
-
- created_at: dt.datetime
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/message.py b/src/speechify/tts/types/message.py
deleted file mode 100644
index 2112717..0000000
--- a/src/speechify/tts/types/message.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from .message_role import MessageRole
-import typing
-import pydantic
-import datetime as dt
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class Message(UniversalBaseModel):
- id: str
- conversation_id: str
- role: MessageRole
- content: str
- tool_name: typing.Optional[str] = None
- tool_args: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None
- tool_result: typing.Optional[typing.Optional[typing.Any]] = pydantic.Field(default=None)
- """
- Arbitrary JSON value returned by the tool (object, array, string, or primitive).
- """
-
- started_at: dt.datetime
- ended_at: typing.Optional[dt.datetime] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/message_role.py b/src/speechify/tts/types/message_role.py
deleted file mode 100644
index decda98..0000000
--- a/src/speechify/tts/types/message_role.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-MessageRole = typing.Union[typing.Literal["user", "assistant", "system", "tool"], typing.Any]
diff --git a/src/speechify/tts/types/mocking_strategy.py b/src/speechify/tts/types/mocking_strategy.py
deleted file mode 100644
index 344c9be..0000000
--- a/src/speechify/tts/types/mocking_strategy.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-MockingStrategy = typing.Union[typing.Literal["none", "all", "selected"], typing.Any]
diff --git a/src/speechify/tts/types/no_match_behavior.py b/src/speechify/tts/types/no_match_behavior.py
deleted file mode 100644
index 29c5374..0000000
--- a/src/speechify/tts/types/no_match_behavior.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-NoMatchBehavior = typing.Union[typing.Literal["call_real_tool", "finish_with_error", "skip"], typing.Any]
diff --git a/src/speechify/tts/types/o_auth_error.py b/src/speechify/tts/types/o_auth_error.py
deleted file mode 100644
index 8eaf2b7..0000000
--- a/src/speechify/tts/types/o_auth_error.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .o_auth_error_error import OAuthErrorError
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class OAuthError(UniversalBaseModel):
- error: typing.Optional[OAuthErrorError] = None
- error_description: typing.Optional[str] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/o_auth_error_error.py b/src/speechify/tts/types/o_auth_error_error.py
deleted file mode 100644
index 3dcbfaf..0000000
--- a/src/speechify/tts/types/o_auth_error_error.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-OAuthErrorError = typing.Union[
- typing.Literal[
- "invalid_client", "unauthorized_client", "invalid_request", "unsupported_grant_type", "invalid_scope"
- ],
- typing.Any,
-]
diff --git a/src/speechify/tts/types/parameter_check.py b/src/speechify/tts/types/parameter_check.py
deleted file mode 100644
index 773a769..0000000
--- a/src/speechify/tts/types/parameter_check.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-from .parameter_check_mode import ParameterCheckMode
-import typing
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class ParameterCheck(UniversalBaseModel):
- """
- Validates one argument of an expected tool call. `path` is a
- dotted JSON path (e.g. `customer.email`); use zero-indexed
- notation for arrays (`items.0.sku`). An empty path checks the
- whole args object.
- """
-
- path: str = pydantic.Field()
- """
- Dotted JSON path to the argument being checked. Empty means the whole args object.
- """
-
- mode: ParameterCheckMode
- expected: typing.Optional[str] = pydantic.Field(default=None)
- """
- Expected value string for `exact` and `regex` modes.
- """
-
- criteria: typing.Optional[str] = pydantic.Field(default=None)
- """
- Natural-language criteria for `llm` mode (e.g. "is a valid email address").
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/parameter_check_mode.py b/src/speechify/tts/types/parameter_check_mode.py
deleted file mode 100644
index 27c6567..0000000
--- a/src/speechify/tts/types/parameter_check_mode.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-ParameterCheckMode = typing.Union[typing.Literal["exact", "regex", "llm"], typing.Any]
diff --git a/src/speechify/tts/types/parameter_check_result.py b/src/speechify/tts/types/parameter_check_result.py
deleted file mode 100644
index 7300a18..0000000
--- a/src/speechify/tts/types/parameter_check_result.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from .parameter_check_mode import ParameterCheckMode
-import pydantic
-import typing
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class ParameterCheckResult(UniversalBaseModel):
- """
- Result of one `ParameterCheck` within a tool-call test run.
- """
-
- path: str
- mode: ParameterCheckMode
- actual_json: str = pydantic.Field()
- """
- JSON-serialised actual value at `path`.
- """
-
- passed: bool
- rationale: typing.Optional[str] = pydantic.Field(default=None)
- """
- LLM rationale (populated for `llm` mode checks).
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/run_agent_tests_response.py b/src/speechify/tts/types/run_agent_tests_response.py
deleted file mode 100644
index eddb061..0000000
--- a/src/speechify/tts/types/run_agent_tests_response.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .agent_test_run import AgentTestRun
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class RunAgentTestsResponse(UniversalBaseModel):
- """
- Response from `POST /v1/agents/{id}/tests/runs`. Contains every
- newly-queued run so the client can poll each for completion.
- Capped at 50 runs per call.
- """
-
- runs: typing.List[AgentTestRun]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/run_batch_response.py b/src/speechify/tts/types/run_batch_response.py
deleted file mode 100644
index 77d0bd6..0000000
--- a/src/speechify/tts/types/run_batch_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .agent_test_run import AgentTestRun
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class RunBatchResponse(UniversalBaseModel):
- runs: typing.List[AgentTestRun]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/scenario_config.py b/src/speechify/tts/types/scenario_config.py
deleted file mode 100644
index 9681422..0000000
--- a/src/speechify/tts/types/scenario_config.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-import pydantic
-from .simulation_message import SimulationMessage
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class ScenarioConfig(UniversalBaseModel):
- """
- Configuration for a `scenario` test. The runner sends `context` as
- a user message and asks an LLM judge to evaluate the agent response
- against `success_criteria`. Optional few-shot examples sharpen the
- judge's calibration. Use `initial_chat_history` to prepend prior
- turns before `context`; when the history already ends with a user
- message, `context` may be omitted and the agent is evaluated on
- its reply to that last history turn.
- """
-
- context: typing.Optional[str] = pydantic.Field(default=None)
- """
- User message sent to the agent to trigger the behaviour under test. Optional when `initial_chat_history` already ends with a user message.
- """
-
- success_criteria: str = pydantic.Field()
- """
- Natural-language description of what a passing agent response looks like.
- """
-
- success_examples: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
- """
- Concrete examples of passing responses (few-shot for the judge).
- """
-
- failure_examples: typing.Optional[typing.List[str]] = pydantic.Field(default=None)
- """
- Concrete examples of failing responses (few-shot for the judge).
- """
-
- initial_chat_history: typing.Optional[typing.List[SimulationMessage]] = pydantic.Field(default=None)
- """
- Optional seed conversation prepended before `context`. Lets you test the agent's reply mid-conversation rather than on a cold single-turn prompt.
- """
-
- system_prompt_override: typing.Optional[str] = pydantic.Field(default=None)
- """
- Replaces the agent's system prompt for this run only. Useful for regression-isolating prompt changes.
- """
-
- first_message_override: typing.Optional[str] = pydantic.Field(default=None)
- """
- Replaces the agent's first message for this run only.
- """
-
- model_override: typing.Optional[str] = pydantic.Field(default=None)
- """
- Overrides the LLM model used by the agent for this run only.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/scenario_result.py b/src/speechify/tts/types/scenario_result.py
deleted file mode 100644
index c3ee1c5..0000000
--- a/src/speechify/tts/types/scenario_result.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import typing
-
-
-class ScenarioResult(UniversalBaseModel):
- """
- Result details for a `scenario` test run.
- """
-
- agent_response: str = pydantic.Field()
- """
- The raw text response the agent produced.
- """
-
- passed: bool
- rationale: str = pydantic.Field()
- """
- LLM judge's explanation of the verdict.
- """
-
- score: float = pydantic.Field()
- """
- 0-1 judge confidence score.
- """
-
- duration_ms: int = pydantic.Field()
- """
- Wall-clock time for the run in milliseconds.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/search_knowledge_bases_response.py b/src/speechify/tts/types/search_knowledge_bases_response.py
deleted file mode 100644
index 14d3769..0000000
--- a/src/speechify/tts/types/search_knowledge_bases_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .knowledge_base_search_hit import KnowledgeBaseSearchHit
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class SearchKnowledgeBasesResponse(UniversalBaseModel):
- hits: typing.List[KnowledgeBaseSearchHit]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/simulation_config.py b/src/speechify/tts/types/simulation_config.py
deleted file mode 100644
index d2a7b38..0000000
--- a/src/speechify/tts/types/simulation_config.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-import typing
-from .simulation_message import SimulationMessage
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class SimulationConfig(UniversalBaseModel):
- """
- Configuration for a `simulation` test. An AI caller drives a
- multi-turn conversation with the agent according to `scenario`.
- After `max_turns` exchanges (or when the agent ends the call), an
- LLM judge evaluates whether `success_condition` was met.
- Use `initial_chat_history` to seed the conversation at a specific
- mid-flow state.
- """
-
- scenario: str = pydantic.Field()
- """
- Instructions for the AI caller describing who they are and what they want.
- """
-
- success_condition: str = pydantic.Field()
- """
- Natural-language description of what a passing conversation looks like.
- """
-
- max_turns: int = pydantic.Field()
- """
- Maximum agent turns before the simulation is cut off and judged.
- """
-
- initial_chat_history: typing.Optional[typing.List[SimulationMessage]] = pydantic.Field(default=None)
- """
- Optional seed conversation that precedes the AI caller's first generated message.
- """
-
- system_prompt_override: typing.Optional[str] = pydantic.Field(default=None)
- """
- Replaces the agent's system prompt for this run only.
- """
-
- model_override: typing.Optional[str] = pydantic.Field(default=None)
- """
- Overrides the LLM model used by the agent for this run only.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/simulation_message.py b/src/speechify/tts/types/simulation_message.py
deleted file mode 100644
index ffb0c0e..0000000
--- a/src/speechify/tts/types/simulation_message.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from .simulation_message_role import SimulationMessageRole
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import typing
-import pydantic
-
-
-class SimulationMessage(UniversalBaseModel):
- """
- One turn in a simulation conversation. `role` is `user` (the AI caller) or `assistant` (the agent).
- """
-
- role: SimulationMessageRole
- content: str
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/simulation_message_role.py b/src/speechify/tts/types/simulation_message_role.py
deleted file mode 100644
index 106ec8f..0000000
--- a/src/speechify/tts/types/simulation_message_role.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-SimulationMessageRole = typing.Union[typing.Literal["user", "assistant"], typing.Any]
diff --git a/src/speechify/tts/types/simulation_result.py b/src/speechify/tts/types/simulation_result.py
deleted file mode 100644
index a6bfb42..0000000
--- a/src/speechify/tts/types/simulation_result.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .simulation_message import SimulationMessage
-import pydantic
-from .simulation_tool_call import SimulationToolCall
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class SimulationResult(UniversalBaseModel):
- """
- Result details for a `simulation` test run.
- """
-
- transcript: typing.List[SimulationMessage] = pydantic.Field()
- """
- Full synthetic conversation in order.
- """
-
- tool_calls: typing.Optional[typing.List[SimulationToolCall]] = pydantic.Field(default=None)
- """
- Every tool invocation across all turns.
- """
-
- turns_used: int = pydantic.Field()
- """
- Number of agent turns that ran before the simulation ended.
- """
-
- passed: bool
- rationale: str = pydantic.Field()
- """
- LLM judge's explanation of the verdict.
- """
-
- duration_ms: int
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/simulation_tool_call.py b/src/speechify/tts/types/simulation_tool_call.py
deleted file mode 100644
index a2781af..0000000
--- a/src/speechify/tts/types/simulation_tool_call.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-import typing
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class SimulationToolCall(UniversalBaseModel):
- """
- One tool invocation that occurred during a simulation run.
- `mocked` is true when the call was intercepted by the run's
- mock config; false when the real tool was called or when the
- tool is a system tool.
- """
-
- turn_index: int = pydantic.Field()
- """
- Zero-based index of the conversation turn in which this call occurred.
- """
-
- tool_name: str
- args: typing.Optional[typing.Any] = None
- response: typing.Optional[typing.Optional[typing.Any]] = pydantic.Field(default=None)
- """
- Response returned to the agent (absent for system tools that end the call).
- """
-
- mocked: bool
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/system_tool_config.py b/src/speechify/tts/types/system_tool_config.py
deleted file mode 100644
index a371652..0000000
--- a/src/speechify/tts/types/system_tool_config.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from .system_tool_config_builtin import SystemToolConfigBuiltin
-import typing
-from .tool_param import ToolParam
-import pydantic
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class SystemToolConfig(UniversalBaseModel):
- """
- Config shape for `kind=system`.
- """
-
- builtin: SystemToolConfigBuiltin
- params: typing.Optional[typing.List[ToolParam]] = None
- builtin_config: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = pydantic.Field(default=None)
- """
- Per-builtin extras (e.g. allowed_numbers for transfer_to_number).
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/system_tool_config_builtin.py b/src/speechify/tts/types/system_tool_config_builtin.py
deleted file mode 100644
index 9c7a630..0000000
--- a/src/speechify/tts/types/system_tool_config_builtin.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-SystemToolConfigBuiltin = typing.Union[
- typing.Literal["end_call", "transfer_to_number", "transfer_to_agent", "play_keypad_touch_tone", "skip_turn"],
- typing.Any,
-]
diff --git a/src/speechify/tts/types/system_variable_doc.py b/src/speechify/tts/types/system_variable_doc.py
deleted file mode 100644
index f3a8627..0000000
--- a/src/speechify/tts/types/system_variable_doc.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import typing
-
-
-class SystemVariableDoc(UniversalBaseModel):
- """
- Documents one reserved `system__*` variable that the platform
- auto-populates at session start. Customers cannot define or
- override these keys.
- """
-
- key: str = pydantic.Field()
- """
- The reserved variable key (always starts with `system__`).
- """
-
- description: str = pydantic.Field()
- """
- What the variable contains and when it is populated.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/tenant.py b/src/speechify/tts/types/tenant.py
deleted file mode 100644
index b1f1263..0000000
--- a/src/speechify/tts/types/tenant.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-from .tenant_plan import TenantPlan
-from .tenant_data_region import TenantDataRegion
-import datetime as dt
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import typing
-
-
-class Tenant(UniversalBaseModel):
- """
- A workspace the caller belongs to.
- """
-
- id: str = pydantic.Field()
- """
- Opaque workspace ID.
- """
-
- name: str = pydantic.Field()
- """
- Display name set by the workspace owner.
- """
-
- plan: TenantPlan = pydantic.Field()
- """
- Billing plan tier.
- """
-
- data_region: TenantDataRegion = pydantic.Field()
- """
- Geographic region the workspace's data is pinned to.
- """
-
- hipaa_mode: bool = pydantic.Field()
- """
- When true, HIPAA-compliant retention and logging is enforced.
- """
-
- zero_retention: bool = pydantic.Field()
- """
- When true, no transcript / audio payloads are retained server-side.
- """
-
- created_at: dt.datetime
- updated_at: dt.datetime
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/tenant_data_region.py b/src/speechify/tts/types/tenant_data_region.py
deleted file mode 100644
index e33656f..0000000
--- a/src/speechify/tts/types/tenant_data_region.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-TenantDataRegion = typing.Union[typing.Literal["us", "eu", "in"], typing.Any]
diff --git a/src/speechify/tts/types/tenant_plan.py b/src/speechify/tts/types/tenant_plan.py
deleted file mode 100644
index e3f98f9..0000000
--- a/src/speechify/tts/types/tenant_plan.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-TenantPlan = typing.Union[typing.Literal["free", "pro", "business", "enterprise"], typing.Any]
diff --git a/src/speechify/tts/types/tenants_list_response.py b/src/speechify/tts/types/tenants_list_response.py
deleted file mode 100644
index e4b7373..0000000
--- a/src/speechify/tts/types/tenants_list_response.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .tenant import Tenant
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class TenantsListResponse(UniversalBaseModel):
- tenants: typing.List[Tenant]
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/test_run_result.py b/src/speechify/tts/types/test_run_result.py
deleted file mode 100644
index 4bfdf28..0000000
--- a/src/speechify/tts/types/test_run_result.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from .test_type import TestType
-import pydantic
-import typing
-from .scenario_result import ScenarioResult
-from .tool_call_result import ToolCallResult
-from .simulation_result import SimulationResult
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class TestRunResult(UniversalBaseModel):
- """
- Union-like result of a completed test run. Exactly one of
- `scenario`, `tool_call`, or `simulation` is populated, matching
- the `test_type`.
- """
-
- test_type: TestType
- passed: bool
- rationale: str = pydantic.Field()
- """
- Top-level verdict explanation duplicated from the inner result for quick rendering.
- """
-
- duration_ms: int
- scenario: typing.Optional[ScenarioResult] = None
- tool_call: typing.Optional[ToolCallResult] = None
- simulation: typing.Optional[SimulationResult] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/test_run_status.py b/src/speechify/tts/types/test_run_status.py
deleted file mode 100644
index f9924f7..0000000
--- a/src/speechify/tts/types/test_run_status.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-TestRunStatus = typing.Union[typing.Literal["queued", "running", "passed", "failed", "error"], typing.Any]
diff --git a/src/speechify/tts/types/test_stats.py b/src/speechify/tts/types/test_stats.py
deleted file mode 100644
index 8a946a6..0000000
--- a/src/speechify/tts/types/test_stats.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .test_stats_bucket import TestStatsBucket
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class TestStats(UniversalBaseModel):
- """
- Aggregate run metrics over the requested window. `buckets` is
- dense - one entry per day in the window, zero-filled, so a chart
- never has gaps. `by_type` counts runs per test type across the
- whole window.
- """
-
- window_days: int
- buckets: typing.List[TestStatsBucket]
- total_runs: int
- passed_runs: int
- failed_runs: int
- errored_runs: int
- avg_duration_ms: int
- by_type: typing.Optional[typing.Dict[str, int]] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/test_stats_bucket.py b/src/speechify/tts/types/test_stats_bucket.py
deleted file mode 100644
index d6d7c26..0000000
--- a/src/speechify/tts/types/test_stats_bucket.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import typing
-
-
-class TestStatsBucket(UniversalBaseModel):
- """
- One daily point on the aggregate pass-rate chart.
- """
-
- day: str = pydantic.Field()
- """
- ISO date (YYYY-MM-DD).
- """
-
- passed: int
- failed: int
- errored: int
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/test_type.py b/src/speechify/tts/types/test_type.py
deleted file mode 100644
index 5afbc08..0000000
--- a/src/speechify/tts/types/test_type.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-TestType = typing.Union[typing.Literal["scenario", "tool", "simulation"], typing.Any]
diff --git a/src/speechify/tts/types/tool.py b/src/speechify/tts/types/tool.py
deleted file mode 100644
index 53a7563..0000000
--- a/src/speechify/tts/types/tool.py
+++ /dev/null
@@ -1,39 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from .tool_kind import ToolKind
-from .tool_config import ToolConfig
-import pydantic
-import typing
-import datetime as dt
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class Tool(UniversalBaseModel):
- id: str
- name: str
- description: str
- kind: ToolKind
- config: ToolConfig = pydantic.Field()
- """
- One of `SystemToolConfig`, `WebhookToolConfig`, or `ClientToolConfig` depending on `kind`.
- """
-
- webhook_secret: typing.Optional[str] = pydantic.Field(default=None)
- """
- HMAC signing secret for `kind=webhook`. Returned in full **only** on the create
- response; all subsequent reads return a masked placeholder. Store it on first
- create — there is no way to retrieve it later.
- """
-
- created_at: dt.datetime
- updated_at: dt.datetime
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/tool_call_config.py b/src/speechify/tts/types/tool_call_config.py
deleted file mode 100644
index 8efecf8..0000000
--- a/src/speechify/tts/types/tool_call_config.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-import pydantic
-from .parameter_check import ParameterCheck
-from .simulation_message import SimulationMessage
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class ToolCallConfig(UniversalBaseModel):
- """
- Configuration for a `tool` test. The runner sends `context` as a
- user message and asserts that the agent calls `expected_tool` with
- arguments matching all `parameter_checks`. Use
- `initial_chat_history` to test tool invocations that only make
- sense mid-conversation.
- """
-
- context: typing.Optional[str] = pydantic.Field(default=None)
- """
- User message that should cause the agent to invoke the expected tool. Optional when `initial_chat_history` already ends with a user message.
- """
-
- expected_tool: str = pydantic.Field()
- """
- Name of the tool the agent is expected to call.
- """
-
- parameter_checks: typing.Optional[typing.List[ParameterCheck]] = pydantic.Field(default=None)
- """
- Assertions on specific arguments of the tool call.
- """
-
- initial_chat_history: typing.Optional[typing.List[SimulationMessage]] = pydantic.Field(default=None)
- """
- Optional seed conversation prepended before `context`.
- """
-
- system_prompt_override: typing.Optional[str] = pydantic.Field(default=None)
- """
- Replaces the agent's system prompt for this run only.
- """
-
- model_override: typing.Optional[str] = pydantic.Field(default=None)
- """
- Overrides the LLM model used by the agent for this run only.
- """
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/tool_call_result.py b/src/speechify/tts/types/tool_call_result.py
deleted file mode 100644
index 7e9dc1c..0000000
--- a/src/speechify/tts/types/tool_call_result.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-import typing
-from .parameter_check_result import ParameterCheckResult
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class ToolCallResult(UniversalBaseModel):
- """
- Result details for a `tool` test run.
- """
-
- tool_called: str = pydantic.Field()
- """
- Name of the tool the agent actually called (may differ from `expected_tool`).
- """
-
- tool_args: typing.Optional[typing.Optional[typing.Any]] = pydantic.Field(default=None)
- """
- Arguments the agent passed to the tool, as a JSON object.
- """
-
- expected_tool: str = pydantic.Field()
- """
- Name of the tool the test expected the agent to call.
- """
-
- tool_matched: bool = pydantic.Field()
- """
- True when `tool_called` equals `expected_tool`.
- """
-
- parameter_results: typing.List[ParameterCheckResult]
- passed: bool
- rationale: str = pydantic.Field()
- """
- Explanation of the overall verdict.
- """
-
- duration_ms: int
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/tool_config.py b/src/speechify/tts/types/tool_config.py
deleted file mode 100644
index ee8576c..0000000
--- a/src/speechify/tts/types/tool_config.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from .system_tool_config import SystemToolConfig
-from .webhook_tool_config import WebhookToolConfig
-from .client_tool_config import ClientToolConfig
-
-ToolConfig = typing.Union[SystemToolConfig, WebhookToolConfig, ClientToolConfig]
diff --git a/src/speechify/tts/types/tool_kind.py b/src/speechify/tts/types/tool_kind.py
deleted file mode 100644
index da3d6ba..0000000
--- a/src/speechify/tts/types/tool_kind.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-ToolKind = typing.Union[typing.Literal["system", "webhook", "client"], typing.Any]
diff --git a/src/speechify/tts/types/tool_mock.py b/src/speechify/tts/types/tool_mock.py
deleted file mode 100644
index 6fe48ca..0000000
--- a/src/speechify/tts/types/tool_mock.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import pydantic
-import typing
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class ToolMock(UniversalBaseModel):
- """
- A canned response returned when the agent calls `tool_name`. If
- `args_match` is set the mock only triggers when its value appears
- as a substring of the JSON-serialised call arguments (a deliberately
- simple v1 matcher — full expression support is planned). A mock
- without `args_match` always matches for its tool.
- """
-
- tool_name: str = pydantic.Field()
- """
- Name of the tool to intercept.
- """
-
- args_match: typing.Optional[str] = pydantic.Field(default=None)
- """
- Optional substring of the JSON-serialised call arguments. When
- absent the mock matches unconditionally for this tool.
- """
-
- response: typing.Optional[typing.Any] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/tool_mock_config.py b/src/speechify/tts/types/tool_mock_config.py
deleted file mode 100644
index 15d5c5e..0000000
--- a/src/speechify/tts/types/tool_mock_config.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from .mocking_strategy import MockingStrategy
-import typing
-from .tool_mock import ToolMock
-import pydantic
-from .no_match_behavior import NoMatchBehavior
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class ToolMockConfig(UniversalBaseModel):
- """
- Controls tool-call interception during a test run.
- """
-
- strategy: MockingStrategy
- mocks: typing.Optional[typing.List[ToolMock]] = pydantic.Field(default=None)
- """
- Canned responses for specific tools (order matters - first match wins).
- """
-
- no_match_behavior: NoMatchBehavior
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/tool_param.py b/src/speechify/tts/types/tool_param.py
deleted file mode 100644
index e5b253f..0000000
--- a/src/speechify/tts/types/tool_param.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-from .tool_param_type import ToolParamType
-import typing
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-import pydantic
-
-
-class ToolParam(UniversalBaseModel):
- """
- One argument the LLM can pass when calling the tool. Mirrors the JSON-Schema subset standard function-calling schemas support.
- """
-
- name: str
- type: ToolParamType
- description: str
- required: bool
- enum: typing.Optional[typing.List[str]] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/tool_param_type.py b/src/speechify/tts/types/tool_param_type.py
deleted file mode 100644
index 9dc5af6..0000000
--- a/src/speechify/tts/types/tool_param_type.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-ToolParamType = typing.Union[typing.Literal["string", "number", "integer", "boolean"], typing.Any]
diff --git a/src/speechify/tts/types/webhook_tool_config.py b/src/speechify/tts/types/webhook_tool_config.py
deleted file mode 100644
index 468e671..0000000
--- a/src/speechify/tts/types/webhook_tool_config.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-from ...core.pydantic_utilities import UniversalBaseModel
-import typing
-from .webhook_tool_config_method import WebhookToolConfigMethod
-import pydantic
-from .tool_param import ToolParam
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
-
-
-class WebhookToolConfig(UniversalBaseModel):
- """
- Config shape for `kind=webhook`.
- """
-
- url: str
- method: typing.Optional[WebhookToolConfigMethod] = None
- headers: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None)
- """
- Static headers sent with every call. `Authorization` and `X-Speechify-Signature` are reserved.
- """
-
- timeout_ms: typing.Optional[int] = pydantic.Field(default=None)
- """
- Per-call timeout in milliseconds.
- """
-
- params: typing.Optional[typing.List[ToolParam]] = None
-
- if IS_PYDANTIC_V2:
- model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
- else:
-
- class Config:
- frozen = True
- smart_union = True
- extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/webhook_tool_config_method.py b/src/speechify/tts/types/webhook_tool_config_method.py
deleted file mode 100644
index f8968f7..0000000
--- a/src/speechify/tts/types/webhook_tool_config_method.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-
-WebhookToolConfigMethod = typing.Union[typing.Literal["POST", "GET"], typing.Any]
diff --git a/src/speechify/tts/voices/client.py b/src/speechify/tts/voices/client.py
index 8eb26e2..ddeaa3a 100644
--- a/src/speechify/tts/voices/client.py
+++ b/src/speechify/tts/voices/client.py
@@ -3,19 +3,25 @@
import typing
from ...core.client_wrapper import SyncClientWrapper
from ...core.request_options import RequestOptions
-from ..types.get_voice import GetVoice
+from ...types.get_voice import GetVoice
from ...core.pydantic_utilities import parse_obj_as
-from ..errors.unauthorized_error import UnauthorizedError
-from ..errors.not_found_error import NotFoundError
-from ..errors.internal_server_error import InternalServerError
+from ...errors.unauthorized_error import UnauthorizedError
+from ...errors.forbidden_error import ForbiddenError
+from ...types.error import Error
+from ...errors.too_many_requests_error import TooManyRequestsError
+from ...errors.internal_server_error import InternalServerError
from json.decoder import JSONDecodeError
from ...core.api_error import ApiError
from .types.create_voices_request_gender import CreateVoicesRequestGender
from ... import core
-from ..types.created_voice import CreatedVoice
-from ..errors.bad_request_error import BadRequestError
-from ..errors.payment_required_error import PaymentRequiredError
+from ...types.created_voice import CreatedVoice
+from ...errors.bad_request_error import BadRequestError
+from ...errors.payment_required_error import PaymentRequiredError
+from ...errors.unprocessable_entity_error import UnprocessableEntityError
+from ...errors.bad_gateway_error import BadGatewayError
+from ...errors.service_unavailable_error import ServiceUnavailableError
from ...core.jsonable_encoder import jsonable_encoder
+from ...errors.not_found_error import NotFoundError
from ...core.client_wrapper import AsyncClientWrapper
# this is used as the default value for optional parameters
@@ -73,12 +79,22 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ty
),
)
)
- if _response.status_code == 404:
- raise NotFoundError(
+ if _response.status_code == 403:
+ raise ForbiddenError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 429:
+ raise TooManyRequestsError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
@@ -86,9 +102,9 @@ def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> ty
if _response.status_code == 500:
raise InternalServerError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
@@ -206,9 +222,39 @@ def create(
if _response.status_code == 402:
raise PaymentRequiredError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 429:
+ raise TooManyRequestsError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
@@ -216,9 +262,29 @@ def create(
if _response.status_code == 500:
raise InternalServerError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 502:
+ raise BadGatewayError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 503:
+ raise ServiceUnavailableError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
@@ -283,6 +349,16 @@ def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] =
),
)
)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
if _response.status_code == 404:
raise NotFoundError(
typing.cast(
@@ -293,12 +369,42 @@ def delete(self, id: str, *, request_options: typing.Optional[RequestOptions] =
),
)
)
+ if _response.status_code == 429:
+ raise TooManyRequestsError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
if _response.status_code == 500:
raise InternalServerError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 502:
+ raise BadGatewayError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 503:
+ raise ServiceUnavailableError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
@@ -370,6 +476,16 @@ def download_sample(
),
)
)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
if _response.status_code == 404:
raise NotFoundError(
typing.cast(
@@ -380,12 +496,42 @@ def download_sample(
),
)
)
+ if _response.status_code == 429:
+ raise TooManyRequestsError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
if _response.status_code == 500:
raise InternalServerError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 502:
+ raise BadGatewayError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 503:
+ raise ServiceUnavailableError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
@@ -455,12 +601,22 @@ async def main() -> None:
),
)
)
- if _response.status_code == 404:
- raise NotFoundError(
+ if _response.status_code == 403:
+ raise ForbiddenError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 429:
+ raise TooManyRequestsError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
@@ -468,9 +624,9 @@ async def main() -> None:
if _response.status_code == 500:
raise InternalServerError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
@@ -596,9 +752,39 @@ async def main() -> None:
if _response.status_code == 402:
raise PaymentRequiredError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 422:
+ raise UnprocessableEntityError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 429:
+ raise TooManyRequestsError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
@@ -606,9 +792,29 @@ async def main() -> None:
if _response.status_code == 500:
raise InternalServerError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 502:
+ raise BadGatewayError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 503:
+ raise ServiceUnavailableError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
@@ -681,6 +887,16 @@ async def main() -> None:
),
)
)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
if _response.status_code == 404:
raise NotFoundError(
typing.cast(
@@ -691,12 +907,42 @@ async def main() -> None:
),
)
)
+ if _response.status_code == 429:
+ raise TooManyRequestsError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
if _response.status_code == 500:
raise InternalServerError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 502:
+ raise BadGatewayError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 503:
+ raise ServiceUnavailableError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
@@ -776,6 +1022,16 @@ async def main() -> None:
),
)
)
+ if _response.status_code == 403:
+ raise ForbiddenError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
if _response.status_code == 404:
raise NotFoundError(
typing.cast(
@@ -786,12 +1042,42 @@ async def main() -> None:
),
)
)
+ if _response.status_code == 429:
+ raise TooManyRequestsError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
if _response.status_code == 500:
raise InternalServerError(
typing.cast(
- typing.Optional[typing.Any],
+ Error,
parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 502:
+ raise BadGatewayError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
+ object_=_response.json(),
+ ),
+ )
+ )
+ if _response.status_code == 503:
+ raise ServiceUnavailableError(
+ typing.cast(
+ Error,
+ parse_obj_as(
+ type_=Error, # type: ignore
object_=_response.json(),
),
)
diff --git a/src/speechify/tts/workspaces/__init__.py b/src/speechify/tts/workspaces/__init__.py
deleted file mode 100644
index f3ea265..0000000
--- a/src/speechify/tts/workspaces/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
diff --git a/src/speechify/tts/workspaces/client.py b/src/speechify/tts/workspaces/client.py
deleted file mode 100644
index ec1fa67..0000000
--- a/src/speechify/tts/workspaces/client.py
+++ /dev/null
@@ -1,2186 +0,0 @@
-# This file was auto-generated by Fern from our API Definition.
-
-import typing
-from ...core.client_wrapper import SyncClientWrapper
-from ...core.request_options import RequestOptions
-from ..types.tenants_list_response import TenantsListResponse
-from ...core.pydantic_utilities import parse_obj_as
-from ..errors.unauthorized_error import UnauthorizedError
-from json.decoder import JSONDecodeError
-from ...core.api_error import ApiError
-from ..types.tenant import Tenant
-from ..errors.bad_request_error import BadRequestError
-from ..errors.not_found_error import NotFoundError
-from ..types.members_list_response import MembersListResponse
-from ..errors.conflict_error import ConflictError
-from ...core.jsonable_encoder import jsonable_encoder
-from ..errors.forbidden_error import ForbiddenError
-from ..types.member_role import MemberRole
-from ..types.member import Member
-from ..types.invites_list_response import InvitesListResponse
-from ..types.invite import Invite
-from ..types.invite_preview import InvitePreview
-from ...core.client_wrapper import AsyncClientWrapper
-
-# this is used as the default value for optional parameters
-OMIT = typing.cast(typing.Any, ...)
-
-
-class WorkspacesClient:
- def __init__(self, *, client_wrapper: SyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> TenantsListResponse:
- """
- List every workspace the authenticated user belongs to. Powers the workspace switcher.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- TenantsListResponse
- Workspaces for the authenticated user.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.workspaces.list()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/tenants",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- TenantsListResponse,
- parse_obj_as(
- type_=TenantsListResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def create(
- self, *, name: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None
- ) -> Tenant:
- """
- Create a new workspace with the authenticated user as owner.
- The caller must switch their active workspace client-side via
- the `X-Tenant-ID` header to act on the new tenant.
-
- Parameters
- ----------
- name : typing.Optional[str]
- Display name for the new workspace. Trimmed; must be 120 characters or fewer.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Tenant
- The newly-created workspace.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.workspaces.create()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/tenants",
- method="POST",
- json={
- "name": name,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Tenant,
- parse_obj_as(
- type_=Tenant, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def get_current(self, *, request_options: typing.Optional[RequestOptions] = None) -> Tenant:
- """
- Retrieve the workspace currently selected by the caller (via `X-Tenant-ID` or auto-resolved).
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Tenant
- The current workspace.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.workspaces.get_current()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/tenants/current",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Tenant,
- parse_obj_as(
- type_=Tenant, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def update_current(self, *, name: str, request_options: typing.Optional[RequestOptions] = None) -> Tenant:
- """
- Rename the current workspace. Owner or admin only.
-
- Parameters
- ----------
- name : str
- New display name. Required; must be 120 characters or fewer.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Tenant
- The updated workspace.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.workspaces.update_current(
- name="name",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/tenants/current",
- method="PATCH",
- json={
- "name": name,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Tenant,
- parse_obj_as(
- type_=Tenant, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_members(self, *, request_options: typing.Optional[RequestOptions] = None) -> MembersListResponse:
- """
- List every member of the current workspace. Any member may call this.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- MembersListResponse
- Members of the current workspace.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.workspaces.list_members()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/tenants/current/members",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- MembersListResponse,
- parse_obj_as(
- type_=MembersListResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def leave(self, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Remove the authenticated caller from the current workspace.
- Refused with 409 when the caller is the last owner — promote
- another member to owner first.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.workspaces.leave()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/tenants/current/members/leave",
- method="POST",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 409:
- raise ConflictError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def remove_member(self, user_uid: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Remove a member from the current workspace. Owner or admin
- only. The caller cannot remove themselves — use
- `POST /v1/tenants/current/members/leave` instead.
-
- Parameters
- ----------
- user_uid : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.workspaces.remove_member(
- user_uid="user_uid",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tenants/current/members/{jsonable_encoder(user_uid)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 403:
- raise ForbiddenError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 409:
- raise ConflictError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def update_member_role(
- self, user_uid: str, *, role: MemberRole, request_options: typing.Optional[RequestOptions] = None
- ) -> Member:
- """
- Change a member's role. Owner only — admins may add or remove
- members but may not change roles. Refused with 409 when
- demoting the last remaining owner.
-
- Parameters
- ----------
- user_uid : str
-
- role : MemberRole
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Member
- The updated member.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.workspaces.update_member_role(
- user_uid="user_uid",
- role="owner",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tenants/current/members/{jsonable_encoder(user_uid)}",
- method="PATCH",
- json={
- "role": role,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Member,
- parse_obj_as(
- type_=Member, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 403:
- raise ForbiddenError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 409:
- raise ConflictError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def list_invites(self, *, request_options: typing.Optional[RequestOptions] = None) -> InvitesListResponse:
- """
- List outstanding invites for the current workspace. Invite tokens are redacted.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- InvitesListResponse
- Outstanding invites.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.workspaces.list_invites()
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/tenants/current/invites",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- InvitesListResponse,
- parse_obj_as(
- type_=InvitesListResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def create_invite(self, *, email: str, request_options: typing.Optional[RequestOptions] = None) -> Invite:
- """
- Create an invite to the current workspace. Owner or admin only.
- The response contains the invite token ONCE — subsequent list
- calls redact it.
-
- Parameters
- ----------
- email : str
- Email of the person to invite. Validated as an RFC 5322 address.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Invite
- The created invite (token included).
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.workspaces.create_invite(
- email="email",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/tenants/current/invites",
- method="POST",
- json={
- "email": email,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Invite,
- parse_obj_as(
- type_=Invite, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 403:
- raise ForbiddenError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def revoke_invite(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Revoke an outstanding invite. Owner or admin only. Idempotent.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.workspaces.revoke_invite(
- id="id",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/tenants/current/invites/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 403:
- raise ForbiddenError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def accept_invite(self, token: str, *, request_options: typing.Optional[RequestOptions] = None) -> Tenant:
- """
- Accept a workspace invite. The authenticated caller is joined
- to the invite's workspace as a member. Expired, revoked, or
- already-accepted tokens return 404 to avoid token enumeration.
-
- Parameters
- ----------
- token : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Tenant
- The workspace the caller just joined.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.workspaces.accept_invite(
- token="token",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/invites/{jsonable_encoder(token)}/accept",
- method="POST",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Tenant,
- parse_obj_as(
- type_=Tenant, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def preview_invite(self, token: str, *, request_options: typing.Optional[RequestOptions] = None) -> InvitePreview:
- """
- Preview a workspace invite without authenticating. Returns the
- workspace name, inviter details, and expiry so the `/join/{token}`
- page can render before the recipient signs in. Anyone with the
- token can already accept, so this endpoint deliberately surfaces
- the same information a caller would see after accepting. Invalid
- tokens (unknown, expired, revoked, already-accepted, or pointing
- at a soft-deleted workspace) collapse to a single 404 to prevent
- enumeration.
-
- Parameters
- ----------
- token : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- InvitePreview
- Preview metadata for a valid, active invite.
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.workspaces.preview_invite(
- token="token",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- f"v1/invites/{jsonable_encoder(token)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- InvitePreview,
- parse_obj_as(
- type_=InvitePreview, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- def transfer_workspace_owner(
- self, *, user_uid: str, request_options: typing.Optional[RequestOptions] = None
- ) -> None:
- """
- Transfer ownership of the current workspace atomically. Promotes
- the target member to owner and demotes the caller to admin in a
- single transaction. Owner-only; admins cannot hand off a role
- they were never granted. Prefer this over two PATCH calls to
- `/v1/tenants/current/members/{user_uid}`: a sole-owner caller
- cannot demote themselves first without tripping the last-owner
- guard, which this endpoint sidesteps by promoting before
- demoting.
-
- Parameters
- ----------
- user_uid : str
- Firebase UID of the member who will become the new owner.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- from speechify import Speechify
-
- client = Speechify(
- token="YOUR_TOKEN",
- )
- client.tts.workspaces.transfer_workspace_owner(
- user_uid="user_uid",
- )
- """
- _response = self._client_wrapper.httpx_client.request(
- "v1/tenants/current/transfer-owner",
- method="POST",
- json={
- "user_uid": user_uid,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 403:
- raise ForbiddenError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
-
-class AsyncWorkspacesClient:
- def __init__(self, *, client_wrapper: AsyncClientWrapper):
- self._client_wrapper = client_wrapper
-
- async def list(self, *, request_options: typing.Optional[RequestOptions] = None) -> TenantsListResponse:
- """
- List every workspace the authenticated user belongs to. Powers the workspace switcher.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- TenantsListResponse
- Workspaces for the authenticated user.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.workspaces.list()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/tenants",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- TenantsListResponse,
- parse_obj_as(
- type_=TenantsListResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def create(
- self, *, name: typing.Optional[str] = OMIT, request_options: typing.Optional[RequestOptions] = None
- ) -> Tenant:
- """
- Create a new workspace with the authenticated user as owner.
- The caller must switch their active workspace client-side via
- the `X-Tenant-ID` header to act on the new tenant.
-
- Parameters
- ----------
- name : typing.Optional[str]
- Display name for the new workspace. Trimmed; must be 120 characters or fewer.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Tenant
- The newly-created workspace.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.workspaces.create()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/tenants",
- method="POST",
- json={
- "name": name,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Tenant,
- parse_obj_as(
- type_=Tenant, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def get_current(self, *, request_options: typing.Optional[RequestOptions] = None) -> Tenant:
- """
- Retrieve the workspace currently selected by the caller (via `X-Tenant-ID` or auto-resolved).
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Tenant
- The current workspace.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.workspaces.get_current()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/tenants/current",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Tenant,
- parse_obj_as(
- type_=Tenant, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def update_current(self, *, name: str, request_options: typing.Optional[RequestOptions] = None) -> Tenant:
- """
- Rename the current workspace. Owner or admin only.
-
- Parameters
- ----------
- name : str
- New display name. Required; must be 120 characters or fewer.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Tenant
- The updated workspace.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.workspaces.update_current(
- name="name",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/tenants/current",
- method="PATCH",
- json={
- "name": name,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Tenant,
- parse_obj_as(
- type_=Tenant, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_members(self, *, request_options: typing.Optional[RequestOptions] = None) -> MembersListResponse:
- """
- List every member of the current workspace. Any member may call this.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- MembersListResponse
- Members of the current workspace.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.workspaces.list_members()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/tenants/current/members",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- MembersListResponse,
- parse_obj_as(
- type_=MembersListResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def leave(self, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Remove the authenticated caller from the current workspace.
- Refused with 409 when the caller is the last owner — promote
- another member to owner first.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.workspaces.leave()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/tenants/current/members/leave",
- method="POST",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 409:
- raise ConflictError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def remove_member(self, user_uid: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Remove a member from the current workspace. Owner or admin
- only. The caller cannot remove themselves — use
- `POST /v1/tenants/current/members/leave` instead.
-
- Parameters
- ----------
- user_uid : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.workspaces.remove_member(
- user_uid="user_uid",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tenants/current/members/{jsonable_encoder(user_uid)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 403:
- raise ForbiddenError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 409:
- raise ConflictError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def update_member_role(
- self, user_uid: str, *, role: MemberRole, request_options: typing.Optional[RequestOptions] = None
- ) -> Member:
- """
- Change a member's role. Owner only — admins may add or remove
- members but may not change roles. Refused with 409 when
- demoting the last remaining owner.
-
- Parameters
- ----------
- user_uid : str
-
- role : MemberRole
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Member
- The updated member.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.workspaces.update_member_role(
- user_uid="user_uid",
- role="owner",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tenants/current/members/{jsonable_encoder(user_uid)}",
- method="PATCH",
- json={
- "role": role,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Member,
- parse_obj_as(
- type_=Member, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 403:
- raise ForbiddenError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 409:
- raise ConflictError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def list_invites(self, *, request_options: typing.Optional[RequestOptions] = None) -> InvitesListResponse:
- """
- List outstanding invites for the current workspace. Invite tokens are redacted.
-
- Parameters
- ----------
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- InvitesListResponse
- Outstanding invites.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.workspaces.list_invites()
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/tenants/current/invites",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- InvitesListResponse,
- parse_obj_as(
- type_=InvitesListResponse, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def create_invite(self, *, email: str, request_options: typing.Optional[RequestOptions] = None) -> Invite:
- """
- Create an invite to the current workspace. Owner or admin only.
- The response contains the invite token ONCE — subsequent list
- calls redact it.
-
- Parameters
- ----------
- email : str
- Email of the person to invite. Validated as an RFC 5322 address.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Invite
- The created invite (token included).
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.workspaces.create_invite(
- email="email",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/tenants/current/invites",
- method="POST",
- json={
- "email": email,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Invite,
- parse_obj_as(
- type_=Invite, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 403:
- raise ForbiddenError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def revoke_invite(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None:
- """
- Revoke an outstanding invite. Owner or admin only. Idempotent.
-
- Parameters
- ----------
- id : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.workspaces.revoke_invite(
- id="id",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/tenants/current/invites/{jsonable_encoder(id)}",
- method="DELETE",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 403:
- raise ForbiddenError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def accept_invite(self, token: str, *, request_options: typing.Optional[RequestOptions] = None) -> Tenant:
- """
- Accept a workspace invite. The authenticated caller is joined
- to the invite's workspace as a member. Expired, revoked, or
- already-accepted tokens return 404 to avoid token enumeration.
-
- Parameters
- ----------
- token : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- Tenant
- The workspace the caller just joined.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.workspaces.accept_invite(
- token="token",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/invites/{jsonable_encoder(token)}/accept",
- method="POST",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- Tenant,
- parse_obj_as(
- type_=Tenant, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def preview_invite(
- self, token: str, *, request_options: typing.Optional[RequestOptions] = None
- ) -> InvitePreview:
- """
- Preview a workspace invite without authenticating. Returns the
- workspace name, inviter details, and expiry so the `/join/{token}`
- page can render before the recipient signs in. Anyone with the
- token can already accept, so this endpoint deliberately surfaces
- the same information a caller would see after accepting. Invalid
- tokens (unknown, expired, revoked, already-accepted, or pointing
- at a soft-deleted workspace) collapse to a single 404 to prevent
- enumeration.
-
- Parameters
- ----------
- token : str
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- InvitePreview
- Preview metadata for a valid, active invite.
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.workspaces.preview_invite(
- token="token",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- f"v1/invites/{jsonable_encoder(token)}",
- method="GET",
- request_options=request_options,
- )
- try:
- if 200 <= _response.status_code < 300:
- return typing.cast(
- InvitePreview,
- parse_obj_as(
- type_=InvitePreview, # type: ignore
- object_=_response.json(),
- ),
- )
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
-
- async def transfer_workspace_owner(
- self, *, user_uid: str, request_options: typing.Optional[RequestOptions] = None
- ) -> None:
- """
- Transfer ownership of the current workspace atomically. Promotes
- the target member to owner and demotes the caller to admin in a
- single transaction. Owner-only; admins cannot hand off a role
- they were never granted. Prefer this over two PATCH calls to
- `/v1/tenants/current/members/{user_uid}`: a sole-owner caller
- cannot demote themselves first without tripping the last-owner
- guard, which this endpoint sidesteps by promoting before
- demoting.
-
- Parameters
- ----------
- user_uid : str
- Firebase UID of the member who will become the new owner.
-
- request_options : typing.Optional[RequestOptions]
- Request-specific configuration.
-
- Returns
- -------
- None
-
- Examples
- --------
- import asyncio
-
- from speechify import AsyncSpeechify
-
- client = AsyncSpeechify(
- token="YOUR_TOKEN",
- )
-
-
- async def main() -> None:
- await client.tts.workspaces.transfer_workspace_owner(
- user_uid="user_uid",
- )
-
-
- asyncio.run(main())
- """
- _response = await self._client_wrapper.httpx_client.request(
- "v1/tenants/current/transfer-owner",
- method="POST",
- json={
- "user_uid": user_uid,
- },
- headers={
- "content-type": "application/json",
- },
- request_options=request_options,
- omit=OMIT,
- )
- try:
- if 200 <= _response.status_code < 300:
- return
- if _response.status_code == 400:
- raise BadRequestError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 401:
- raise UnauthorizedError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 403:
- raise ForbiddenError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- if _response.status_code == 404:
- raise NotFoundError(
- typing.cast(
- typing.Optional[typing.Any],
- parse_obj_as(
- type_=typing.Optional[typing.Any], # type: ignore
- object_=_response.json(),
- ),
- )
- )
- _response_json = _response.json()
- except JSONDecodeError:
- raise ApiError(status_code=_response.status_code, body=_response.text)
- raise ApiError(status_code=_response.status_code, body=_response_json)
diff --git a/src/speechify/types/__init__.py b/src/speechify/types/__init__.py
new file mode 100644
index 0000000..4736402
--- /dev/null
+++ b/src/speechify/types/__init__.py
@@ -0,0 +1,47 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from .create_voice_language import CreateVoiceLanguage
+from .create_voice_model import CreateVoiceModel
+from .create_voice_model_name import CreateVoiceModelName
+from .created_voice import CreatedVoice
+from .created_voice_gender import CreatedVoiceGender
+from .created_voice_type import CreatedVoiceType
+from .error import Error
+from .error_code import ErrorCode
+from .error_detail import ErrorDetail
+from .get_speech_options_request import GetSpeechOptionsRequest
+from .get_speech_response import GetSpeechResponse
+from .get_speech_response_audio_format import GetSpeechResponseAudioFormat
+from .get_stream_options_request import GetStreamOptionsRequest
+from .get_voice import GetVoice
+from .get_voice_gender import GetVoiceGender
+from .get_voice_language import GetVoiceLanguage
+from .get_voice_type import GetVoiceType
+from .get_voices_model import GetVoicesModel
+from .get_voices_model_name import GetVoicesModelName
+from .nested_chunk import NestedChunk
+from .speech_marks import SpeechMarks
+
+__all__ = [
+ "CreateVoiceLanguage",
+ "CreateVoiceModel",
+ "CreateVoiceModelName",
+ "CreatedVoice",
+ "CreatedVoiceGender",
+ "CreatedVoiceType",
+ "Error",
+ "ErrorCode",
+ "ErrorDetail",
+ "GetSpeechOptionsRequest",
+ "GetSpeechResponse",
+ "GetSpeechResponseAudioFormat",
+ "GetStreamOptionsRequest",
+ "GetVoice",
+ "GetVoiceGender",
+ "GetVoiceLanguage",
+ "GetVoiceType",
+ "GetVoicesModel",
+ "GetVoicesModelName",
+ "NestedChunk",
+ "SpeechMarks",
+]
diff --git a/src/speechify/tts/types/create_voice_language.py b/src/speechify/types/create_voice_language.py
similarity index 82%
rename from src/speechify/tts/types/create_voice_language.py
rename to src/speechify/types/create_voice_language.py
index b60313b..16226ad 100644
--- a/src/speechify/tts/types/create_voice_language.py
+++ b/src/speechify/types/create_voice_language.py
@@ -1,8 +1,8 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.pydantic_utilities import UniversalBaseModel
+from ..core.pydantic_utilities import UniversalBaseModel
import typing
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
+from ..core.pydantic_utilities import IS_PYDANTIC_V2
import pydantic
diff --git a/src/speechify/tts/types/create_voice_model.py b/src/speechify/types/create_voice_model.py
similarity index 85%
rename from src/speechify/tts/types/create_voice_model.py
rename to src/speechify/types/create_voice_model.py
index 9f97b91..458d356 100644
--- a/src/speechify/tts/types/create_voice_model.py
+++ b/src/speechify/types/create_voice_model.py
@@ -1,10 +1,10 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.pydantic_utilities import UniversalBaseModel
+from ..core.pydantic_utilities import UniversalBaseModel
import typing
from .create_voice_language import CreateVoiceLanguage
from .create_voice_model_name import CreateVoiceModelName
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
+from ..core.pydantic_utilities import IS_PYDANTIC_V2
import pydantic
diff --git a/src/speechify/types/create_voice_model_name.py b/src/speechify/types/create_voice_model_name.py
new file mode 100644
index 0000000..e82711f
--- /dev/null
+++ b/src/speechify/types/create_voice_model_name.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+CreateVoiceModelName = typing.Union[typing.Literal["simba-english", "simba-multilingual", "simba-3.0"], typing.Any]
diff --git a/src/speechify/tts/types/created_voice.py b/src/speechify/types/created_voice.py
similarity index 87%
rename from src/speechify/tts/types/created_voice.py
rename to src/speechify/types/created_voice.py
index 6eba08b..fcbaf1f 100644
--- a/src/speechify/tts/types/created_voice.py
+++ b/src/speechify/types/created_voice.py
@@ -1,11 +1,11 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.pydantic_utilities import UniversalBaseModel
+from ..core.pydantic_utilities import UniversalBaseModel
import typing
from .created_voice_gender import CreatedVoiceGender
from .create_voice_model import CreateVoiceModel
from .created_voice_type import CreatedVoiceType
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
+from ..core.pydantic_utilities import IS_PYDANTIC_V2
import pydantic
diff --git a/src/speechify/tts/types/created_voice_gender.py b/src/speechify/types/created_voice_gender.py
similarity index 100%
rename from src/speechify/tts/types/created_voice_gender.py
rename to src/speechify/types/created_voice_gender.py
diff --git a/src/speechify/tts/types/created_voice_type.py b/src/speechify/types/created_voice_type.py
similarity index 100%
rename from src/speechify/tts/types/created_voice_type.py
rename to src/speechify/types/created_voice_type.py
diff --git a/src/speechify/types/error.py b/src/speechify/types/error.py
new file mode 100644
index 0000000..8346a5b
--- /dev/null
+++ b/src/speechify/types/error.py
@@ -0,0 +1,38 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from ..core.pydantic_utilities import UniversalBaseModel
+from .error_detail import ErrorDetail
+import typing
+import pydantic
+from ..core.pydantic_utilities import IS_PYDANTIC_V2
+
+
+class Error(UniversalBaseModel):
+ """
+ Standard error envelope returned on every non-2xx response.
+ Content-Type is `application/json`. The shape mirrors OpenAI /
+ Anthropic / Stripe style: a machine-readable `error.code` for
+ SDK consumers to switch on, a human `error.message` for UI,
+ and an optional `error.fields` map for per-field validation
+ errors. `request_id` matches the `X-Request-ID` response
+ header and is what customers quote when filing support
+ tickets.
+ """
+
+ error: ErrorDetail
+ request_id: typing.Optional[str] = pydantic.Field(default=None)
+ """
+ Server-side request identifier. Echoes the
+ `X-Request-ID` response header. Stable across the
+ request's lifetime, written to structured logs, and
+ useful when reporting issues.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/speechify/types/error_code.py b/src/speechify/types/error_code.py
new file mode 100644
index 0000000..1a0139e
--- /dev/null
+++ b/src/speechify/types/error_code.py
@@ -0,0 +1,48 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+ErrorCode = typing.Union[
+ typing.Literal[
+ "bad_request",
+ "validation_failed",
+ "unauthorized",
+ "payment_required",
+ "forbidden",
+ "not_found",
+ "method_not_allowed",
+ "conflict",
+ "payload_too_large",
+ "unsupported_media_type",
+ "rate_limited",
+ "internal_error",
+ "upstream_failure",
+ "service_unavailable",
+ "caller_not_found",
+ "credential_not_found",
+ "agent_not_found",
+ "kb_not_found",
+ "kb_document_not_found",
+ "kb_folder_not_found",
+ "tool_not_found",
+ "conversation_not_found",
+ "phone_number_not_found",
+ "sip_trunk_not_found",
+ "voice_not_found",
+ "audio_asset_not_found",
+ "builtin_not_found",
+ "batch_not_found",
+ "agent_test_not_found",
+ "workspace_not_found",
+ "invite_not_found",
+ "insufficient_scope",
+ "purchased_numbers_not_included",
+ "phone_number_quota_reached",
+ "batch_calls_not_included",
+ "voice_cloning_not_included",
+ "workspace_last_owner",
+ "workspace_last_workspace",
+ "invite_email_mismatch",
+ ],
+ typing.Any,
+]
diff --git a/src/speechify/types/error_detail.py b/src/speechify/types/error_detail.py
new file mode 100644
index 0000000..e0dd4d6
--- /dev/null
+++ b/src/speechify/types/error_detail.py
@@ -0,0 +1,37 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from ..core.pydantic_utilities import UniversalBaseModel
+from .error_code import ErrorCode
+import pydantic
+import typing
+from ..core.pydantic_utilities import IS_PYDANTIC_V2
+
+
+class ErrorDetail(UniversalBaseModel):
+ code: ErrorCode
+ message: str = pydantic.Field()
+ """
+ Human-readable explanation of this specific occurrence.
+ Safe to surface in UI banners or pass to support. The
+ wording can change between releases; clients should
+ match on `code`, not on the message string.
+ """
+
+ fields: typing.Optional[typing.Dict[str, str]] = pydantic.Field(default=None)
+ """
+ Per-field validation errors as `path -> message`. Only
+ present on 400 responses caused by request validation
+ (typically code=`validation_failed`). Keys are field
+ paths in dotted/bracket notation; values are short
+ human explanations safe to inline-surface next to the
+ offending form field.
+ """
+
+ if IS_PYDANTIC_V2:
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
+ else:
+
+ class Config:
+ frozen = True
+ smart_union = True
+ extra = pydantic.Extra.allow
diff --git a/src/speechify/tts/types/get_speech_options_request.py b/src/speechify/types/get_speech_options_request.py
similarity index 93%
rename from src/speechify/tts/types/get_speech_options_request.py
rename to src/speechify/types/get_speech_options_request.py
index 3e2f52e..2c840e4 100644
--- a/src/speechify/tts/types/get_speech_options_request.py
+++ b/src/speechify/types/get_speech_options_request.py
@@ -1,9 +1,9 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.pydantic_utilities import UniversalBaseModel
+from ..core.pydantic_utilities import UniversalBaseModel
import typing
import pydantic
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
+from ..core.pydantic_utilities import IS_PYDANTIC_V2
class GetSpeechOptionsRequest(UniversalBaseModel):
diff --git a/src/speechify/tts/types/get_speech_response.py b/src/speechify/types/get_speech_response.py
similarity index 89%
rename from src/speechify/tts/types/get_speech_response.py
rename to src/speechify/types/get_speech_response.py
index 3943cdf..9763919 100644
--- a/src/speechify/tts/types/get_speech_response.py
+++ b/src/speechify/types/get_speech_response.py
@@ -1,10 +1,10 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.pydantic_utilities import UniversalBaseModel
+from ..core.pydantic_utilities import UniversalBaseModel
import pydantic
from .get_speech_response_audio_format import GetSpeechResponseAudioFormat
from .speech_marks import SpeechMarks
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
+from ..core.pydantic_utilities import IS_PYDANTIC_V2
import typing
diff --git a/src/speechify/tts/types/get_speech_response_audio_format.py b/src/speechify/types/get_speech_response_audio_format.py
similarity index 100%
rename from src/speechify/tts/types/get_speech_response_audio_format.py
rename to src/speechify/types/get_speech_response_audio_format.py
diff --git a/src/speechify/tts/types/get_stream_options_request.py b/src/speechify/types/get_stream_options_request.py
similarity index 93%
rename from src/speechify/tts/types/get_stream_options_request.py
rename to src/speechify/types/get_stream_options_request.py
index 96ece1f..65136a0 100644
--- a/src/speechify/tts/types/get_stream_options_request.py
+++ b/src/speechify/types/get_stream_options_request.py
@@ -1,9 +1,9 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.pydantic_utilities import UniversalBaseModel
+from ..core.pydantic_utilities import UniversalBaseModel
import typing
import pydantic
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
+from ..core.pydantic_utilities import IS_PYDANTIC_V2
class GetStreamOptionsRequest(UniversalBaseModel):
diff --git a/src/speechify/tts/types/get_voice.py b/src/speechify/types/get_voice.py
similarity index 88%
rename from src/speechify/tts/types/get_voice.py
rename to src/speechify/types/get_voice.py
index 0466b56..6153004 100644
--- a/src/speechify/tts/types/get_voice.py
+++ b/src/speechify/types/get_voice.py
@@ -1,11 +1,11 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.pydantic_utilities import UniversalBaseModel
+from ..core.pydantic_utilities import UniversalBaseModel
import typing
from .get_voice_gender import GetVoiceGender
from .get_voices_model import GetVoicesModel
from .get_voice_type import GetVoiceType
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
+from ..core.pydantic_utilities import IS_PYDANTIC_V2
import pydantic
diff --git a/src/speechify/tts/types/get_voice_gender.py b/src/speechify/types/get_voice_gender.py
similarity index 100%
rename from src/speechify/tts/types/get_voice_gender.py
rename to src/speechify/types/get_voice_gender.py
diff --git a/src/speechify/tts/types/get_voice_language.py b/src/speechify/types/get_voice_language.py
similarity index 81%
rename from src/speechify/tts/types/get_voice_language.py
rename to src/speechify/types/get_voice_language.py
index 3062016..92d6cc6 100644
--- a/src/speechify/tts/types/get_voice_language.py
+++ b/src/speechify/types/get_voice_language.py
@@ -1,8 +1,8 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.pydantic_utilities import UniversalBaseModel
+from ..core.pydantic_utilities import UniversalBaseModel
import typing
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
+from ..core.pydantic_utilities import IS_PYDANTIC_V2
import pydantic
diff --git a/src/speechify/tts/types/get_voice_type.py b/src/speechify/types/get_voice_type.py
similarity index 100%
rename from src/speechify/tts/types/get_voice_type.py
rename to src/speechify/types/get_voice_type.py
diff --git a/src/speechify/tts/types/get_voices_model.py b/src/speechify/types/get_voices_model.py
similarity index 84%
rename from src/speechify/tts/types/get_voices_model.py
rename to src/speechify/types/get_voices_model.py
index d68df75..fec07ba 100644
--- a/src/speechify/tts/types/get_voices_model.py
+++ b/src/speechify/types/get_voices_model.py
@@ -1,10 +1,10 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.pydantic_utilities import UniversalBaseModel
+from ..core.pydantic_utilities import UniversalBaseModel
import typing
from .get_voice_language import GetVoiceLanguage
from .get_voices_model_name import GetVoicesModelName
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
+from ..core.pydantic_utilities import IS_PYDANTIC_V2
import pydantic
diff --git a/src/speechify/types/get_voices_model_name.py b/src/speechify/types/get_voices_model_name.py
new file mode 100644
index 0000000..7ec7d98
--- /dev/null
+++ b/src/speechify/types/get_voices_model_name.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+GetVoicesModelName = typing.Union[typing.Literal["simba-english", "simba-multilingual", "simba-3.0"], typing.Any]
diff --git a/src/speechify/tts/types/nested_chunk.py b/src/speechify/types/nested_chunk.py
similarity index 88%
rename from src/speechify/tts/types/nested_chunk.py
rename to src/speechify/types/nested_chunk.py
index d842e83..b19d967 100644
--- a/src/speechify/tts/types/nested_chunk.py
+++ b/src/speechify/types/nested_chunk.py
@@ -1,8 +1,8 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.pydantic_utilities import UniversalBaseModel
+from ..core.pydantic_utilities import UniversalBaseModel
import typing
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
+from ..core.pydantic_utilities import IS_PYDANTIC_V2
import pydantic
diff --git a/src/speechify/tts/types/speech_marks.py b/src/speechify/types/speech_marks.py
similarity index 88%
rename from src/speechify/tts/types/speech_marks.py
rename to src/speechify/types/speech_marks.py
index d0bc925..dc225d2 100644
--- a/src/speechify/tts/types/speech_marks.py
+++ b/src/speechify/types/speech_marks.py
@@ -1,10 +1,10 @@
# This file was auto-generated by Fern from our API Definition.
-from ...core.pydantic_utilities import UniversalBaseModel
+from ..core.pydantic_utilities import UniversalBaseModel
import typing
from .nested_chunk import NestedChunk
import pydantic
-from ...core.pydantic_utilities import IS_PYDANTIC_V2
+from ..core.pydantic_utilities import IS_PYDANTIC_V2
class SpeechMarks(UniversalBaseModel):