Decide between generating and hand-writing a client
Count the operations, schemas and parameters you would maintain, then decide between a generated client and one you write on the numbers rather than on taste.
How-to › Section 6
Choosing how to produce client libraries, generating them, making them idiomatic, composing runtime features, customizing a generator without forking, adding languages, and regenerating safely.
10 guides in 6 topics. Every guide compares its approaches and shows the output its commands printed.
Deciding and doing: a repeatable rubric for hand-written versus generated versus AI-written versus SaaS-generated SDKs (total cost of ownership, per-seat pricing, determinism measured across two runs, entity-shaped versus endpoint-shaped output measured rather than asserted), then running OpenAPI Generator, Swagger Codegen, Kiota, Speakeasy, Stainless, Fern, liblab, oapi-codegen, openapi-typescript with openapi-fetch, orval, Hey API, openapi-python-client, NSwag, AutoRest, Smithy, and sdkgen (npm create @voxgig/sdkgen, target add, --only, --dryrun), judging the output (the voxgig-solardemo-sdk Go reference and the elementdemo repo as things to read before choosing), and migrating from one generator to another while keeping package names and semver continuity.
Count the operations, schemas and parameters you would maintain, then decide between a generated client and one you write on the numbers rather than on taste.
Scaffold a project from your OpenAPI document with one non-interactive command, generate a TypeScript SDK, and read what the model made of your endpoints.
Count the nouns, the operations per noun, and how many names start with a verb, so a claim about SDK shape is a measurement rather than a preference.
What makes an SDK feel native: entities versus endpoint wrappers, constructor and configuration, method naming, options objects versus builders, sync and async variants, cancellation (context.Context, AbortSignal), typed errors, nullable handling, response envelopes, ESM and CJS dual builds, and escape hatches for raw requests (sdkgen direct and prepare, Stainless raw responses, OpenAPI Generator withHttpInfo).
Give a Ruby client keyword-argument methods and Data response objects, let callers add Faraday middleware, and prove a wrong keyword raises before any request.
How cross-cutting behaviors fit together inside one client, plus the behaviors that have no protocol branch of their own.
Send three identifiers with three lifetimes, so a support question about one call can be answered from the service's own logs.
Compose retry, caching, authentication and tracing as layers around one transport, so each concern is written once and the order is declared rather than implied.
Bending generated output without a fork, with every page showing the same customization in at least one other generator: OpenAPI Generator custom templates and .openapi-generator-ignore, Speakeasy overlays and hooks, Fern custom code, Kiota, and the six sdkgen levers (model .aon files with project.aon never overwritten, templates in .sdk/tm, TypeScript components in .sdk/src/cmp, custom features with per-stage hooks, custom targets, and sdkgen packages with package add, check, list, update), plus docs add, the flags --only, --alias, --force, --dryrun and --debug, typed models, doctor in CI, installing a third-party sdkgen package such as @voxgig/sdkgen-haskell or sdkgen-station, propagating template changes, migrating a bundled target out of tree, driving generation from a script with the programmatic API, and debugging generation.
Record what the generator shipped, compare the project against it on every build, and separate a file you forked from a file you added.
Write a client's computed parts, a dispatch table and an overload matrix, as a function over the typed model, and hold its output to a formatted fixture.
Adding a language to an SDK programme: how to grade targets yourself when the generator does not (sdkgen publishes 22 bundled targets plus package-delivered ones such as Haskell, and grades none of them; OpenAPI Generator labels each generator's stability; Speakeasy publishes a supported-language list), what less polished should mean to you, packaging expectations per ecosystem, and authoring a new target (sdkgen author-a-new-language, OpenAPI Generator new-generator scaffolding, the Fern generator API).
Run one fixed evaluation on a candidate language target, record what you measured beside the generator's claims, and decide who supports it before it ships.
Regeneration as a routine operation: three-way merge against the last generation, preserve and protect markers, diff mode, overwrite policies, reviewing a regeneration diff, failing CI when a regenerated SDK differs from the committed one, vendoring and upgrade migration, keeping hand edits in separate files.
See exactly what a generator would change before it changes anything, with a dry run that reports creates, replacements, and the files its mode protects.
Retries, timeouts, pagination and auth are the same problems in every client. Voxgig generates them from your OpenAPI description, in 23 languages, from one model.