> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vobiz.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# PLAN

# 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
> \~$250/mo **per SDK** — ~$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

```
fern/
├── fern.config.json            # org + pinned CLI version
├── generators.yml              # all 7 languages → local-file-system output
└── openapi/
    ├── openapi.yml             # Fern reads this; auto-synced from root openapi.yaml
    └── overrides.yml           # SDK-only patches (auth is auto; mostly empty)

.github/workflows/              # INSTALLED & LIVE in this repo (no longer under fern/)
├── generate-sdks.yml           # sync spec → regenerate → commit SDKs on spec change
├── publish-typescript.yml      # → npm        (OIDC, free)
├── publish-python.yml          # → PyPI       (OIDC, free)
├── publish-go.yml              # → mirror to vobiz-ai/vobiz-go + git tag
├── publish-java.yml            # → Maven Central (Sonatype Central Portal, vanniktech)
├── publish-ruby.yml            # → RubyGems
├── publish-csharp.yml          # → NuGet
└── publish-php.yml             # → mirror to vobiz-ai/vobiz-php → Packagist

sdks/<lang>/                    # generated SDK source (committed). Java build.gradle +
                                # settings.gradle + gradle.properties are HAND-AUTHORED.
```

Languages: **TypeScript, Python, Go, Java, Ruby, C#, PHP.** (Kotlin dropped per scope;
Fern supports Swift/Rust too if wanted later.)

***

## 2. How the free pipeline works end-to-end

```
edit fern/openapi/openapi.yml  →  push to main
        │
        ▼
generate-sdks.yml (GitHub Action)
  • npm i -g fern-api
  • fern generate --local            ← Apache-2.0 generators run in Docker, FREE
  • writes idiomatic source to sdks/<lang>/
  • commits sdks/ back to the repo
        │
        ▼
tag a release  (e.g. `git tag python-v1.2.0 && git push --tags`)
        │
        ▼
publish-<lang>.yml (GitHub Action)
  • builds the package in sdks/<lang>/
  • publishes to npm / PyPI / Maven / RubyGems / NuGet / Packagist
        │
        ▼
package live on the registry      ← all on free GitHub Actions minutes
```

Two human actions: **edit the spec** and **tag a release**. Everything between is
automated, and nothing bills you (GitHub Actions public-repo minutes are free).

***

## 3. One-time setup runbook

### A. Spec repo

1. Create `vobiz-ai/vobiz-api-spec`. Move this `fern/` folder to its root, move
   `fern/workflows/*` to `.github/workflows/`, and keep `openapi.yml` as the source of truth.
   (Or run it all from this Mintlify docs repo — the spec already lives here.)

### B. Fern token — NOT NEEDED ✅ (verified)

2. `npm install -g fern-api`. **No token or login is required for `fern generate --local`** — tested empirically: the command runs the open-source generator
   Docker images straight away, with no auth prompt. There is **no `FERN_TOKEN`
   secret** anywhere in the pipeline. (Use `--force` in CI to skip the interactive
   "overwrite existing files?" confirmation.)

### C. First generation (verify package manifests — see §4)

3. Locally: `fern generate --local --force` (Docker must be running — no token needed).
   Inspect each `sdks/<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 the `vobiz-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)                                                               | —                     |

**Plus, for every language:** the single `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!

5. Push a spec change → `generate-sdks.yml` commits SDKs → tag `python-v0.1.0` etc.
   → `publish-*.yml` ships 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's `securitySchemes`
(`X-Auth-ID` = `AuthId`, `X-Auth-Token` = `AuthToken`, combined with AND in one
`security` requirement). Both surface as client constructor options:

```ts theme={null}
const client = new Vobiz({ authId: "…", authToken: "…" });
```

No extra config needed. To rename the params, add `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)**                |

What we give up vs. paid: the auto-injected Mintlify `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-codeSamples` is a paid feature. Free
  alternative: keep Mintlify's built-in `examples.languages` (curl/python/javascript)
  that `docs.json` already enables, or hand-add a few `x-codeSamples` for 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 own `vobiz-ai/vobiz-<lang>` repo, extend the mirror pattern in
  `publish-go.yml`/`publish-php.yml` to the others.
* **Spec hardening (carried over)**: complete the `make-call`/`record`/`play`/`speak`
  request schemas, fix `/account/`→`/Account/` casing, name reused inline schemas. Fern
  reads schemas, not examples — same Phase-1 work as the Stainless plan. Do it in
  `openapi.yml` (or surgically in `overrides.yml`).

***

## 8. Verify-before-trust list (flagged from research)

1. **Package manifests on free tier** (§4) — confirm empirically per language.
2. ~~Whether `--local` needs `FERN_TOKEN`~~ **RESOLVED: no token/login needed.** Verified
   empirically — `fern generate --local` runs the open-source generators with zero auth.
3. **Generator image versions** in `generators.yml` — bump to latest tags at setup
   (pinned values were current at authoring).
4. **Java/Ruby/C#/PHP config keys** (`group-id`, `clientClassName`, `namespace`,
   `packageName`) — verify exact names on each generator's `…/configuration` page.
5. **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-go` and
   `vobiz-ai/vobiz-php` exist.

Sources: buildwithfern.com/learn/sdks/\* (quickstarts, configuration, publishing,
self-hosted, how-it-works), hub.docker.com/u/fernapi, buildwithfern.com/pricing.
