API Advice
Choosing an SDK vendor: Speakeasy vs Fern vs Stainless vs openapi-codegen

Nolan Sullivan
May 28, 2025 - 16 min read

Without an SDK for your API, your users must handle raw HTTP requests themselves, leading to integration delays, avoidable bugs, and higher support costs. Even with good documentation, not having an SDK can slow adoption, frustrate developers, and increase churn.
A well-designed SDK improves developer experience. It saves time, reduces integration errors, speeds up onboarding, and – importantly – can drive adoption and revenue.
Today, you no longer need to build SDKs manually. Several tools generate SDKs from an OpenAPI document, including Speakeasy
But with so many options available, how do you know which will save you the most time? Which generator will create SDKs that are easy to use, extend, and won’t break when your API grows? Which will let you focus on building features instead of fixing generated code?
In this article, we compare the main SDK generation options available today. We’ll explain their strengths, weaknesses, and differences to help you decide which best suits your needs.
What to look for in an SDK generator
It’s not enough to focus solely on the code produced when evaluating an SDK generator. You also need to consider factors impacting the SDK’s developer experience (for internal and external devs) and how well the tool fits your workflow and budget:
- OpenAPI support: Does the generator fully support the OpenAPI Specification, including handling schema validation and pagination?
- OAuth 2.0 support: Does the generator handle OAuth client credentials properly, including token fetching and refreshing?
- Webhooks support: Can the generator validate, parse, and process webhook events securely and reliably?
- Generated documentation and examples: Does the generated SDK come with ready-to-use documentation and copy-paste examples for everyday API operations, making it easier for developers to get started quickly?
- SDK quality and structure: Is the generated code readable, idiomatic, and easy to navigate? Does the generator produce ready-to-publish packages with minimal dependencies, or does it create bloated, messy code that your team would need to clean up?
- Streaming support: Does the generator produce SDKs that properly handle large uploads and downloads using streams?
- SDK automation and CI/CD integration: Can the generator integrate into your CI/CD pipeline and automatically regenerate SDKs as your API evolves?
- SDK customization options: Does the tool let you customize naming, structure, and the SDK’s behavior when necessary?
- Pricing: Is the pricing transparent, scalable, and startup-friendly?
Here’s a quick comparison of how each SDK generator performs across these criteria.
Feature | Speakeasy | Fern | Stainless | OpenAPI Typescript Codegen |
---|---|---|---|---|
OpenAPI support | ✅ Full support for OpenAPI 3.0 and 3.1 | ✅ Supports OpenAPI 3.1 | ⚠️ Limited; best results with custom format | ✅ Supports OpenAPI 2.0 and 3.0 |
SDK quality (ready-to-publish packages) | ✅ Yes | ✅ Yes | ✅ Yes | ⚠️ Basic structure |
OAuth 2.0 / runtime validation | ✅ Built-in schema validation | ✅ Built-in schema validation | ✅ Built-in schema validation | ❌ Not supported |
Webhooks support | ✅ Full support | ⚠️ Helper methods | ❌ Not supported | ❌ Not supported |
Streaming support | ✅ Uploads/downloads via streams | ⚠️ Limited (Fern Definition only) | ⚠️ Enterprise-only | ❌ Not supported |
Documentation and examples | ✅ Auto-generated docs and examples | ⚠️ Basic with OpenAPI | ⚠️ Basic; best with Stainless configuration | ❌ Minimal documentation |
SDK automation and CI/CD integration | ✅ GitHub Action / CI-ready | ✅ CLI / GitHub Action | ⚠️ Manual CLI | ✅ Easy CLI integration |
SDK customization options | ✅ High (OpenAPI extensions, overrides) | ⚠️ High, but via Fern Definition | ⚠️ Requires custom format | ⚠️ Limited (template edits) |
Pagination handling | ✅ Automatic support | ✅ Auto-pagination | ⚠️ Manual configuration needed | ❌ Manual |
Retries built-in | ✅ Yes | ✅ Yes | ✅ Yes | ❌ Manual |
Pricing | Free tier; paid plans from $250/mo | Paid plans from $250/mo | Free tier; paid plans from $250/mo | Free (open source) |
Not sure which tool to pick? Here’s how to choose based on your priorities:
- Choose Speakeasy if you want the most complete feature set with the least manual work and you’re OpenAPI-first.
- Choose Fern if you need maximum control over SDK structure and don’t mind a more complex setup.
- Choose OpenAPI Typescript Codegen if you need a fast, open-source solution for basic TypeScript SDKs.
Speakeasy
Speakeasy’s approach to SDK generation focuses on real-world API usage, offering advanced features and minimizing developer friction. Because Speakeasy uses OpenAPI documents to generate SDKs, it’s a compelling choice for API-first teams.
OpenAPI support
Speakeasy fully supports OpenAPI versions 3.0 and 3.1.
As Speakeasy relies on your OpenAPI documents to generate SDKs, the quality of those documents directly impacts the results. To help ensure that OpenAPI documents are clean, accurate, and complete, Speakeasy validates them before generation, catching issues like missing required fields in requests or server responses that don’t match the documented schema.
For example, when sending a payload, if your OpenAPI document marks a field as required, the SDK will enforce it at the client level:
If the email field is missing, the SDK throws a validation error without making a request.
Speakeasy also handles pagination patterns natively. Whether your API uses offset, cursor, or custom pagination logic, Speakeasy can generate helper functions that abstract pagination away from the user. For example:
No need to manually manage cursors, tokens, or page offsets.
SDK quality and structure
Speakeasy-generated SDKs are production-ready by default – idiomatic for each target language, aligned with community best practices, and free of bloated, deeply nested, or unreadable structures.
Each SDK is designed for immediate publishing to registries like npm, PyPI, and Maven Central, with sensible package structure, typed clients, and minimal external dependencies.
OAuth 2.0 support
Speakeasy supports OAuth 2.0 out of the box. If your OpenAPI document defines an OAuth 2.0 security scheme, Speakeasy automatically detects it and generates SDK code that manages tokens on behalf of your users, including requesting tokens, handling expirations, and refreshing them when needed.
Configuring OAuth in your OpenAPI document
Let’s take a look at how to define an OAuth 2.0 client credentials flow in an OpenAPI document:
Once this security scheme is defined in an OpenAPI document, Speakeasy-generated SDKs will prompt SDK users to provide a clientID
and clientSecret
when initializing the client:
Behind the scenes, the SDK will:
- Automatically fetch an access token from the token URL.
- Retry requests with a fresh token if the current one has expired.
- Add the
Bearer <token>
Authorization header for authenticated requests.
No additional code is needed to manage token lifetimes for this flow.
Customizing token retrieval
For more advanced scenarios, such as integrating with nonstandard token endpoints or using custom headers during token exchange, you can write your token retrieval logic and pass it to the SDK:
This allows complete control over how tokens are requested, validated, cached, and refreshed.
NOTE
To support flows like resource owner password credentials, authorization code, or custom schemes, you must update your OpenAPI document accordingly and use Speakeasy SDK hooks for additional logic.
Webhooks support
Speakeasy offers automatic webhook event validation and parsing. For example, it can generate functions that automatically verify webhook signatures and parse the payload correctly according to the OpenAPI event schema:
This automatic verification and parsing ensures security and reduces the chances of mishandling or misparsing critical webhook notifications.
Streaming support
Speakeasy supports streaming for download and upload endpoints – essential when handling large files or long-lived server responses. Instead of buffering the whole file in memory, risking performance issues or crashes, SDKs expose the response as a stream.
To enable this behavior, define the endpoint in your OpenAPI document using the application/octet-stream
content type with a binary format:
This tells the SDK generator to treat the response as a raw byte stream. In a TypeScript SDK, the download logic becomes clean and efficient:
Here, the sdk.streamable("UR123")
call fetches a ReadableStream
. The Node.js Writable.toWeb()
method converts a standard file stream to a format compatible with the browser-style Streams API. Then pipeTo()
streams the API’s ReadableStream
directly into the writable file stream, avoiding full in-memory buffering.
Generated documentation and examples
Alongside SDKs, Speakeasy automatically generates documentation in README.md
, RUNTIMES.md
, FUNCTIONS.md
, and USAGE.md
files. The docs include concise usage examples (like creating a resource, retries, and authentication) based directly on your OpenAPI document.
Developers get the SDK package and a browsable documentation site located in the docs
directory, ready to deploy.
SDK automation and CI/CD integration
Speakeasy supports fully automated SDK generation. It can integrate directly in your CI/CD pipelines (for example, in GitHub Actions or GitLab CI/CD) so that when you update your OpenAPI document, SDKs are rebuilt and published automatically, without manual intervention.
SDK customization options
Speakeasy provides flexible configuration for naming, error handling, retry strategies, pagination settings, and more, either through OpenAPI extensions or project-specific overrides.
You can fine-tune the SDK to match your API’s particular design patterns or your engineering team’s preferences.
Pricing
Speakeasy isn’t open source but offers a hosted SDK management platform with automated generation, publishing, and updates. The free tier includes one SDK in a single language with GitHub integration and access to the complete OpenAPI toolchain. Paid plans start at $250/month and unlock features like pagination support and multi-language output. Higher tiers offer webhook support, event streaming, test generation, and enterprise-grade service-level agreements (SLAs).
Fern
Fern is a modern SDK generator built around its domain-specific language, Fern Definition
OpenAPI support
Fern
The Fern OpenAPI parser covers most standard use cases. However, it is sensitive to inconsistent patterns and may miss edge cases like unconventional pagination and loosely defined endpoints. If standard pagination fields like next_cursor
or offset
are clearly described in the Fern Definition, the parser can recognize them and generate SDK methods accordingly.
Link pagination is not supported, and the customization offset
and results
fields:
Speakeasy numPages
, results
, and nextCursor
, so Speakeasy knows how to handle auto-pagination.
SDK quality and structure
Fern SDKs tend to be deeply nested and verbose. The generated TypeScript code includes multiple layers of abstraction and utility wrappers, making it hard to follow what’s being executed. Request logic is often hidden behind custom serializers, and the separation between core logic and API-specific behavior is unclear. Naming conventions are inconsistent, and common operations span too many files, making the SDKs harder to read, debug, or extend.
See the SDK structure section of our Speakeasy vs Fern post for an overview of the Fern SDK structure.
OAuth 2.0 support
Fern can generate SDKs that support bearer token authentication (OAuth 2.0 access tokens)
For example, a Fern TypeScript SDK configuration with OAuth 2.0 would look like this:
The Fern SDK supports authorization flows such as client-credentials
and authorization-code
, but doesn’t support more advanced or legacy flows like resource_owner_password
. Also, you can’t implement custom auth flows with Fern because there’s no extensibility mechanism.
By contrast, Speakeasy provides full flexibility via SDK hooks
Webhooks support
Fern SDKs provide a constructEvent helper
That said, Fern leaves much of the responsibility for webhook handling to the developer. You must manually configure secrets, map the correct headers, and implement any error handling, replay protection, or logging logic.
Streaming support
Fern supports binary uploads using the bytes
type in the Fern Definition, allowing you to model raw binary payloads (like MP3 or image files) as the request body. Fern expects type: file
for responses, which allows the SDK to treat the returned data as a streamable file. However, this streaming behavior is only available when using Fern Definition. If you rely on OpenAPI, you must manually handle both uploads and downloads, without stream helpers.
Generated documentation and examples
If you use Fern Definition, the generated SDKs include well-structured inline documentation and developer-friendly examples of API operations. When working directly from OpenAPI without Fern-specific metadata, the generated SDK documentation is more basic and lacks detailed examples.
The SDKs still include method signatures and basic type hints, but they rely heavily on how much information is in your original OpenAPI document.
SDK automation and CI/CD integration
Fern provides tools that automate SDK generation
SDK customization options
If you adopt the Fern Definition, Fern is highly customizable. You can configure naming conventions, error handling structures, pagination strategies, custom SDK behavior, and even the generated documentation. However, this flexibility comes with vendor lock-in. In many cases, you’ll have to manage two sources of truth: your OpenAPI document and the Fern Definition.
Speakeasy, on the other hand, lets you use a single OpenAPI document as the source of truth. For more custom behavior, you can write SDK hooks, update the OpenAPI document directly, or use an Arazzo definition
Fern also allows custom code augmentation
Pricing
Fern’s starter plan
Stainless
Stainless is an SDK generation platform built around a custom configuration format rather than native OpenAPI support. Stainless produces polished SDKs with a clean developer experience, but it requires additional setup and manual integration for many advanced features.
OpenAPI support
Stainless partially supports the OpenAPI Specification
If your OpenAPI document is your stack’s single source of truth, you’ll run into limitations unless you migrate to the Stainless domain-specific language.
SDK quality and structure
Stainless prioritizes clean SDKs with minimal dependencies and idiomatic formatting. However, the SDK layout lacks structure: Models, operations, and helpers are often mixed without clear separation. Tracing what’s actually happening under the hood can take time.
Error handling is thin, so expect to wire up your retry logic, response decoding, and fallback behavior.
OAuth 2.0 support
Stainless-generated SDKs do not manage OAuth tokens for you. Instead, developers must fetch access tokens manually and inject them into the client’s headers.
There’s no built-in retry, refresh, or expiration handling — you’re on your own for all lifecycle logic.
Webhooks support
Stainless doesn’t support webhooks. If you define webhook events, you’ll need to implement your own verification (for example, HMAC or RSA) and deserialization logic. There’s no helper like constructEvent()
or built-in type-safe handler — just raw payloads.
Streaming support
Streaming support is only available for Enterprise customers.
Generated documentation and examples
Stainless SDKs generated from OpenAPI documents have limited inline documentation. Migrating to the Stainless format improves documentation quality, but compared to other generators like Speakeasy or Fern, Stainless provides fewer ready-to-use examples.
SDK automation and CI/CD integration
Stainless supports automation for OpenAPI updates
However, Stainless does not provide a full CI/CD pipeline for SDK generation and publication beyond uploading your OpenAPI document. You’re still responsible for managing SDK builds, versioning, and publishing to registries like npm or PyPI. Compared to platforms like Speakeasy that offer end-to-end automation – from OpenAPI document to SDK release – Stainless requires more manual setup and maintenance.
SDK customization options
Customization is only available when using the Stainless format. Using a plain OpenAPI document limits your ability to customize SDK behavior. Teams that want fine-grained control over SDK structure must migrate to Stainless’s configuration file format.
Pricing
Stainless offers a free plan with one local SDK and up to 50 endpoints
OpenAPI Typescript Codegen
OpenAPI Typescript Codegen is a lightweight, open-source CLI tool that generates TypeScript or JavaScript SDKs directly from OpenAPI documents. While the tool is minimalistic and simple to set up, it requires significant manual work to produce production-grade SDKs.
OpenAPI support
OpenAPI Typescript Codegen fully supports OpenAPI 2.0 and 3.0 but interprets OpenAPI documents very literally: If the document lacks examples, pagination metadata, or detailed schemas, the generated SDK will be incomplete or inaccurate. The tool provides no built-in understanding of pagination patterns (such as offset- or cursor-based approaches) or advanced specification features like polymorphism with oneOf
and anyOf
. The quality of the generated SDK depends heavily on the precision of the OpenAPI document provided.
SDK quality and structure
The SDK generated by OpenAPI Typescript Codegen is clean but extremely basic: A simple folder structure (/models
, /services
), low-level HTTP wrappers using Fetch or Axios, and minimal or no error handling for API failures. The SDK feels closer to an API client scaffold than a complete developer experience platform.
OAuth 2.0 support
OpenAPI Typescript Codegen does not offer built-in helpers for OAuth flows. The developer must manually handle authentication, and token management and refresh logic must be implemented outside the SDK.
Webhooks support
The generator does not natively support webhook validation, parsing, or handling. It focuses on REST API clients and does not extend to webhook server-side integrations.
Streaming support
Streaming is not natively supported. Large uploads and downloads must be manually handled by adjusting Fetch or Axios request configurations.
Generated documentation and examples
OpenAPI Typescript Codegen generates basic inline TypeScript typings and function signatures. It does not provide ready-to-use examples or rich developer documentation. Developers are expected to rely on TypeScript’s IntelliSense to navigate the SDK. There are no tutorials or built-in guides alongside the generated code.
SDK automation and CI/CD integration
Since it is a simple CLI tool, OpenAPI Typescript Codegen
A typical GitHub Action step might look like this:
Automation is straightforward but requires custom scripting for tasks like versioning, publishing, and changelog generation.
SDK customization options
OpenAPI Typescript Codegen has limited support for SDK customization. Developers can modify templates slightly, but advanced customization like changing naming conventions or response handling requires forking the tool or manually post-processing the output.
Pricing
OpenAPI Typescript Codegen is fully open source
Final thoughts
If you are building an API product, you probably already have an OpenAPI document available – or you should.
When choosing an SDK generator, prioritize tools that offer complete, native support for OpenAPI without requiring custom formats, workarounds, or extensive manual adjustments. Ultimately, the best SDK generator is the one that fits your team’s workflow, spec quality, and appetite for customization.
If you are looking for a tool that fully supports OpenAPI, helps you generate high-quality SDKs with minimal manual work, and makes it easier to ship faster, it’s worth checking out the Speakeasy tools.