Skip to content

feat!: regenerate SDK for API 2026-09-30 with simba-3.5 - #38

Merged
vitalragaz merged 274 commits into
mainfrom
feat/regenerate-2026-09-30
Oct 29, 2026
Merged

vitalragaz merged 274 commits into
mainfrom
feat/regenerate-2026-09-30

Conversation

@vitalragaz

@vitalragaz vitalragaz commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

speechify-api catches up with the API: simba-3.5, projects, workspaces, audio watermark verification and webhook endpoints, with API version 2026-09-30 as the default. Merging releases 5.0.0.

Why: Fern pushed every regeneration since August to sdk-release and nobody merged it, so 4.0.0 predates simba-3.5. This branch merges sdk-release, then takes every generated file from Fern's own regeneration of SpeechifyInc/speechify-api main (#39: python generator 5.41.10, origin 14383dab) and keeps this branch's hand-kept files. Future regenerations arrive as PRs like #39.

What to look at

  • SpeechifyEnvironment.DEFAULT has base and websocket. The WebSocket URL used to be called production because of the AsyncAPI server's name. SpeechifyInc/speechify-api#4744 renames that server, so the name is right in the same major that turns the environment into a class.
  • Audio calls raise ContentTooLargeError on 413, because the spec declares it on the synthesis operations. With-timestamps streaming still yields the declared SpeechStreamEvent_* classes, and a test pins that.
  • The client reads SPEECHIFY_API_KEY when it is built, not at import. Generator 5.41.10 resolves the token in the constructor, so a key set after import speechify (for example by load_dotenv()) is used. An explicit token= still wins. This is fix(auth): resolve environment token when constructing clients (proof of concept) #34's fix, now from the generator.
  • A missing key still does not raise at construction. POST /v1/audio/watermark/verify takes no credentials, so a keyless client has to be able to call it. Without a key, the first authenticated call raises UnauthorizedError (401 unauthorized). Proposed follow-up in speechify-api: make that 401 message name SPEECHIFY_API_KEY.
  • Other 5.41.10 changes in generated code: stream reconnection options (stream_reconnection_enabled, max_stream_reconnection_attempts) on the client and per request, a timeout request option (timeout_in_seconds stays as a deprecated alias), opt-in retry_remote_protocol_errors, empty SSE data lines skipped, and mypy passing under pydantic 2.14 natively, so the earlier hand patch is gone.
  • pyproject.toml license is the generator's PEP 639 form ([project] license = "MIT", license-files). Poetry 1.5.1, which publishes, still writes License: MIT and the MIT classifier; current poetry-core writes License-Expression: MIT. The version stays 4.0.0, so release-please computes 5.0.0.
  • README. No Websockets section: it documented client.audio.stream_input, which this SDK does not have. Examples use simba-3.5, matching what SpeechifyInc/speechify-api#4741's spec generates, and the timeout example uses timeout.
  • tests/custom/test_client.py (hand-kept, in .fernignore): offline tests of a client built with defaults, sync and async. Environment, URL, Bearer header, one Speechify-Version across resource clients, a with-timestamps stream framed as the API writes it, the 413, no Authorization without a key, the 401 without a key, a key set after import being used, and an explicit token beating the environment.

Merge order and follow-ups

How verified

  • CI on d280838 (Python 3.10, Poetry 1.5.1): compile (mypy) and test pass.
  • Local, Python 3.12, lockfile pydantic 2.14.1: pytest 103 passed, 3 skipped (aiohttp not installed; 106 passed with the extra). mypy .: no issues in 176 files.
  • The two new env-var tests fail against this branch's previous 5.14.20 client.py and pass on 5.41.10.
  • Offline smoke, no credits: Speechify() with the key set after import sends audio.speech() to https://api.speechify.ai/v1/audio/speech with the Bearer header and Speechify-Version: 2026-09-30. request_options={"timeout": 1} reaches httpx as a 1 s timeout.
  • Live, keyless, no credits: models.list() and audio.speech() raise UnauthorizedError 401 {"error":{"code":"unauthorized","message":"Unauthorized"}}. audio.watermark.verify() answers watermarked=False.
  • The tree differs from SDK regeneration #39 only in hand-kept files: AGENTS.md, README.md, reference.md, .fernignore, tests/custom/test_client.py, and the 4.0.0 version in pyproject.toml and .fern/metadata.json.
Investigation detail
  • Merge commit 48cb2c9: every generated path checked out from fern-bot/2026-10-27_16-45-54_696 (33e10e7), hand-kept files from this branch. Fern's .fern/replay.lock, .gitattributes and their .fernignore lines are in; tests/custom/test_client.py stays in .fernignore.
  • Build check: poetry build (1.5.1) gives License: MIT, Classifier: License :: OSI Approved :: MIT License and LICENSE in dist-info. python -m build with poetry-core 2.5.0 gives Metadata-Version: 2.4, License-Expression: MIT, License-File: LICENSE. twine check passes both.
  • An earlier revision of SpeechifyInc/speechify-api#4744 added x-fern-discriminator-context: protocol to the stream union for the TypeScript SDK. In Python that yields SpeechChunkEvent/SpeechDoneEvent cast to the SpeechStreamEvent_* union, so isinstance checks fail. The annotation was dropped, and the stream test fails if it comes back.
  • The audio calls now map 409 to ConflictError, as the spec declares.

BREAKING CHANGE: the default API version moves to 2026-09-30, base_url is gone, and SpeechifyEnvironment is a class with base and websocket.

  • Requests now send Speechify-Version: 2026-09-30 instead of 2026-09-13. On that version simba-english and simba-multilingual return 400 model_retired, and output_format="pcm_16000" returns real 16 kHz audio instead of 24 kHz bytes labelled 16 kHz.
  • To keep the 4.x wire behaviour, pin the version: Speechify(version="2026-09-13")
  • Speechify(base_url=...) and AsyncSpeechify(base_url=...) are removed. For a custom URL, pass environment=SpeechifyEnvironment(base="https://...", websocket="wss://...").
  • SpeechifyEnvironment is a plain class, not an Enum, so SpeechifyEnvironment.DEFAULT.value becomes SpeechifyEnvironment.DEFAULT.base.
  • A client built without a key no longer raises at construction. The first authenticated call raises UnauthorizedError instead.

BEGIN_COMMIT_OVERRIDE
feat!: regenerate SDK for API 2026-09-30 with simba-3.5

BREAKING CHANGE: API version 2026-09-30 is the default, SpeechifyEnvironment is a class with base and websocket URLs, and base_url is removed. See PR #38 for the migration.
END_COMMIT_OVERRIDE

fern-api Bot and others added 17 commits October 8, 2026 10:38
…rom main

Conflicts resolved by rule: every Fern-generated file comes from sdk-release
(840e0cb regeneration); every .fernignore-listed file and the release-please
state (pyproject [tool.poetry].version, .fern/metadata.json sdkVersion) comes
from main.
pydantic 2.14 (the lockfile's version) makes mypy report var-annotated on the
two module-level TypeAdapter instances, which failed the release-please job.
These are the exact lines Fern's python generator emits from 5.39.2, which
SpeechifyInc/speechify-api moves to, so the next regeneration leaves them as
they are. Constraining pydantic below 2.14 would have narrowed users' runtime
dependency to work around our own type check.
…ve, examples use simba-3.5

client.audio.stream_input does not exist: the python generator only builds
websocket clients with should_generate_websocket_clients, but its README
feature list documented the AsyncAPI channel anyway. SpeechifyInc/speechify-api
now sets readme.disabledSections: [websockets], and this is exactly the README
that setting generates. The speech, stream and voices examples move to
simba-3.5, the recommended model, as the spec's examples do.
Covers what no generated test does: a client built with defaults sends
audio.speech to https://api.speechify.ai, every resource client sends the
same Speechify-Version, and a keyless client sends no Authorization header
(POST /v1/audio/watermark/verify takes no credentials).
@vitalragaz
vitalragaz marked this pull request as draft October 27, 2026 15:48
Regenerated from SpeechifyInc/speechify-api#4744's spec, which renames the
AsyncAPI server from production to websocket. The same spec declares 413 on
the synthesis operations, so audio calls now raise ContentTooLargeError.
tests/custom/test_client.py pins the environment, reads a with-timestamps
stream framed as the API writes it into the declared SpeechStreamEvent_*
classes, and checks the 413.
@vitalragaz
vitalragaz marked this pull request as ready for review October 27, 2026 16:11
fern-api Bot and others added 4 commits October 27, 2026 16:45
Generated by Fern
CLI Version: unknown
Generators:
  - fernapi/fern-python-sdk: 5.41.10
…kept files from this branch

Generated files come from Fern's regeneration of SpeechifyInc/speechify-api
main (14383dab, python generator 5.41.10). Hand-kept files stay as this
branch has them: AGENTS.md, README.md and reference.md (the simba-3.5
examples), tests/custom/test_client.py and its .fernignore line.

README takes the generator's "timeout" request option, which 5.41.10 adds
(timeout_in_seconds stays as a deprecated alias). pyproject.toml and
.fern/metadata.json keep 4.0.0, so release-please computes 5.0.0; the PEP 639
license fields are the generator's output for license: MIT.
Generator 5.41.10 resolves the token at construction instead of in a default
argument evaluated at import, so a key set after `import speechify` is used.
An explicit token still wins, a keyless client sends no Authorization header,
and an authenticated call without a key raises UnauthorizedError.
@vitalragaz
vitalragaz merged commit 62f7ef7 into main Oct 29, 2026
7 checks passed
@vitalragaz
vitalragaz deleted the feat/regenerate-2026-09-30 branch October 29, 2026 13:10
vitalragaz pushed a commit that referenced this pull request Oct 29, 2026
🤖 I have created a release *beep* *boop*
---


##
[5.0.0](4.0.0...5.0.0)
(2026-10-29)


### ⚠ BREAKING CHANGES

* API version 2026-09-30 is the default, SpeechifyEnvironment is a class
with base and websocket URLs, and base_url is removed. See PR #38 for
the migration.

### Features

* regenerate SDK for API 2026-09-30 with simba-3.5
([62f7ef7](62f7ef7))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant