Vobiz SDKs — Free, self-managed pipeline with Fern
Why this exists: Stainless (the original plan in../stainless/) was acquired by
Anthropic and is closed to new users. This is the replacement: Fern’s open-source,
Apache-2.0 generators produce idiomatic SDKs from the same openapi.yaml, and our
own GitHub Actions publish them to registries. Total tooling cost: $0/mo.
Cost honesty. Fern’s managed pipeline (auto-publishing, managed repos) is ~1,750/mo for 7 languages. We do not use it. We use only the free local generators + our own CI. The trade-off: we own the publish wiring (this folder already scaffolds it) and the package manifests (see §4).
1. What’s in this folder
2. How the free pipeline works end-to-end
3. One-time setup runbook
A. Spec repo
- Create
vobiz-ai/vobiz-api-spec. Move thisfern/folder to its root, movefern/workflows/*to.github/workflows/, and keepopenapi.ymlas the source of truth. (Or run it all from this Mintlify docs repo — the spec already lives here.)
B. Fern token — NOT NEEDED ✅ (verified)
npm install -g fern-api. No token or login is required forfern generate --local— tested empirically: the command runs the open-source generator Docker images straight away, with no auth prompt. There is noFERN_TOKENsecret anywhere in the pipeline. (Use--forcein CI to skip the interactive “overwrite existing files?” confirmation.)
C. First generation (verify package manifests — see §4)
- Locally:
fern generate --local --force(Docker must be running — no token needed). Inspect eachsdks/<lang>/for a package manifest (package.json,pyproject.toml,go.mod,*.csproj,composer.json,*.gemspec). If missing → §4.
D. Architecture: mirror-into-each-repo
Each language has its own public repo under thevobiz-ai org. This docs repo
generates + commits sdks/<lang>/; on a <lang>-v* tag the publish workflow injects
the version, publishes to the registry, and mirrors sdks/<lang>/ into that repo +
tags it. The per-language repos are source mirrors (and the actual release channel
for Go + PHP). One shared SDK_PUSH_TOKEN (a vobiz-ai member/bot PAT with Contents
write) powers all seven mirrors.
| Language | Mirror repo (vobiz-ai/…) | Registry | One-time setup | Registry secret |
|---|---|---|---|---|
| TypeScript | Vobiz-Node-SDK | npm | Trusted Publisher for @vobiz/sdk → repo devlume-in/Mintlyfy-Docs + publish-typescript.yml | none (OIDC) |
| Python | Vobiz-Python-SDK | PyPI | Pending publisher for vobiz → same repo + publish-python.yml | none (OIDC) |
| Go | Vobiz-Go-SDK | — (git tag) | Module path must equal repo URL github.com/vobiz-ai/Vobiz-Go-SDK (set ✔). Consider a lowercase vobiz-go repo for a clean go get. | — |
| Java | Vobiz-Java-SDK ⚠️ create | Maven Central | Verify ai.vobiz namespace (DNS TXT) + GPG key | SONATYPE_*, GPG_* |
| Ruby | Vobiz-Ruby-SDK | RubyGems | API key, “Push” scope | GEM_HOST_API_KEY |
| C# | Vobiz-Csharp-sdk | NuGet | API key, “Push” scope | NUGET_API_KEY |
| PHP | Vobiz-PHP-SDK ⚠️ create | Packagist | Submit vobiz-ai/Vobiz-PHP-SDK, enable GitHub hook (version comes from tag) | — |
SDK_PUSH_TOKEN secret.
Optional — AI READMEs: set GEMINI_API_KEY (repo secret on devlume-in/Mintlyfy-Docs).
generate-sdks.yml then runs fern/scripts/generate-readme.mjs after every generation to
overwrite each Fern-template README with a detailed, source-grounded one (Gemini
gemini-2.5-flash by default; set GEMINI_MODEL=gemini-2.5-pro for max quality). If the
key is unset the step no-ops and keeps the existing README, so it never blocks the build.
This also makes the good READMEs durable — they’re rewritten on each regen instead of
reverting to Fern’s template.
E. Go!
- Push a spec change →
generate-sdks.ymlcommits SDKs → tagpython-v0.1.0etc. →publish-*.ymlships each package.
4. The package-manifest caveat (the one real catch)
Fern’s free--local generation reliably emits SDK source code. Package-metadata
files (package.json, pyproject.toml, go.mod, README) are documented as added when
Fern “completes the SDK” — and the Python quickstart explicitly says pyproject.toml
and README.md are generated only on paid plans. So on the free tier some manifests
may be missing.
This does not block the free path. If a manifest is missing, commit a thin
hand-authored one into sdks/<lang>/ (you control name/version/deps). The publish
workflows already assume the manifest lives in the SDK folder. You write each manifest
once; regeneration only rewrites the source, not your manifest.
Status (verified empirically): 6/7 manifests were emitted on the free tier —
TS package.json, Python pyproject.toml, Go go.mod, PHP composer.json,
Ruby vobiz.gemspec, C# Vobiz.csproj+Vobiz.slnx. Only Java had no build file,
exactly as predicted — now hand-authored at sdks/java/build.gradle (+ settings.gradle,
gradle.properties), using the vanniktech maven-publish plugin → Sonatype Central Portal.
⚠️ Its dependency versions weren’t compile-verified (no local JDK); run gradle build
in sdks/java/ once before the first java-v* tag.
5. Auth (handled automatically)
The dual-header scheme is read straight from the spec’ssecuritySchemes
(X-Auth-ID = AuthId, X-Auth-Token = AuthToken, combined with AND in one
security requirement). Both surface as client constructor options:
x-fern-header in overrides.yml.
6. Honest assessment vs. the old Stainless plan
| Stainless (dead) | Fern managed ($1,750/mo) | Fern free (this) | |
|---|---|---|---|
| Cost | n/a (closed) | ~$250/mo × 7 | $0 |
| SDK quality | excellent | excellent | idiomatic (same generators) |
| Generation automation | full | full | full (our CI) |
| Publish automation | full | full | full (our CI, we wired it) |
| Package manifests | provided | provided | we author missing ones once (§4) |
| Mintlify code samples | built-in | built-in | not free — see §7 |
| Vendor lock / disappear risk | (gone) | low (Postman-backed) | none (Apache-2.0) |
x-codeSamples loop and Fern’s
managed release PRs. Both are replaceable (see §7) or simply nice-to-haves.
7. Optional follow-ups
- Mintlify code samples: Fern’s auto-
x-codeSamplesis a paid feature. Free alternative: keep Mintlify’s built-inexamples.languages(curl/python/javascript) thatdocs.jsonalready enables, or hand-add a fewx-codeSamplesfor hero endpoints. - Separate per-language repos: this scaffold is a monorepo (all SDKs in
sdks/). Go and PHP already mirror out to their own repos (registry requirement). If you want every SDK in its ownvobiz-ai/vobiz-<lang>repo, extend the mirror pattern inpublish-go.yml/publish-php.ymlto the others. - Spec hardening (carried over): complete the
make-call/record/play/speakrequest schemas, fix/account/→/Account/casing, name reused inline schemas. Fern reads schemas, not examples — same Phase-1 work as the Stainless plan. Do it inopenapi.yml(or surgically inoverrides.yml).
8. Verify-before-trust list (flagged from research)
- Package manifests on free tier (§4) — confirm empirically per language.
WhetherRESOLVED: no token/login needed. Verified empirically —--localneedsFERN_TOKENfern generate --localruns the open-source generators with zero auth.- Generator image versions in
generators.yml— bump to latest tags at setup (pinned values were current at authoring). - Java/Ruby/C#/PHP config keys (
group-id,clientClassName,namespace,packageName) — verify exact names on each generator’s…/configurationpage. - Go/PHP own-repo mirroring — the module path / Packagist registration require the
SDK to live in its own repo; the mirror workflows assume
vobiz-ai/vobiz-goandvobiz-ai/vobiz-phpexist.