Speakeasy Logo
Skip to Content

API Advice

In Depth: Speakeasy vs Stainless

Nolan Sullivan

Nolan Sullivan

January 10, 2025 - 8 min read

API Advice

In this post, we’ll compare generated SDKs, as well as the underlying philosophies that guide the development of the two companies. And while we acknowledge that our views may be biased, we’ll show our work along with our conclusions so that readers can decide for themselves.

In short: How is Speakeasy different?

OpenAPI-native vs OpenAPI-compatible

Speakeasy is OpenAPI-native; Stainless is OpenAPI-compatible. Stainless is built on a custom DSL known as the Stainless config . This approach requires your team to manage an additional config file. Speakeasy has no intermediary DSL. Your OpenAPI spec is the only source of truth for SDK generation.

Being OpenAPI-native is beneficial for integration into an existing stack. Regardless of the API proxies, server-side code, or specific web framework that you’re using, you can plug in Speakeasy’s tools. Stainless is doubling down on a vertically integrated approach by building a backend TypeScript framework  which will become the foundation for their solution. Their product will work best when you buy the entire stack, Speakeasy will shine regardless of the other tools in your existing stack.

Type-safe vs type-faith

There’s more on this topic in the technical deep dive below. Speakeasy SDKs guarantee true end-to-end type safety, meaning that types are generated to validate both request and response objects defined in your API. Stainless SDKs, on the other hand, are mainly type-hinted, not guarding the API from bad inputs.

Velocity and maturity

Stainless was founded in 2021  and has expanded its language support to seven languages. By comparison, Speakeasy launched in October 2022 and has released support for ten languages in less time. The Speakeasy platform is also broader, with support for additional generation features, like webhooks, React Hooks, and contract testing, not supported by Stainless.

Both companies are financially secure, having raised $25M+ in funding.

Platform

Platform Comparison

Product
SDK generation
Speakeasy
Stainless
Terraform generation
Speakeasy
Stainless
Docs generation
Speakeasy
Stainless
Contract testing
Speakeasy
Stainless
E2E testing
Speakeasy
Stainless

SDK generation

SDK Language Support

Language
TypeScript
Speakeasy
Stainless
Python
Speakeasy
Stainless
Go
Speakeasy
Stainless
Java
Speakeasy
Stainless
Kotlin
Speakeasy
⚠ Java is Kotlin-compatible
Stainless
Ruby
Speakeasy
Stainless
C#
Speakeasy
Stainless
PHP
Speakeasy
Stainless
Swift
Speakeasy
Stainless
Unity
Speakeasy
Stainless

If there’s a language you require that we don’t support, add it to our roadmap .

SDK features

Breadth matters, but so does the depth of support for each language. The table below shows the current feature support for Speakeasy and Stainless’s SDK generation.

SDK Feature Comparison

Feature
Webhooks support
Speakeasy
Stainless
React Hooks
Speakeasy
Stainless
OAuth 2.0
Speakeasy
Stainless
❌ (manual)
React Hooks support
Speakeasy
Stainless
❌ (manual)
Retries
Speakeasy
Stainless
Pagination
Speakeasy
Stainless
Async functions
Speakeasy
Stainless
Streaming uploads
Speakeasy
Stainless
Custom SDK naming
Speakeasy
Stainless
Union types
Speakeasy
Stainless
Discriminated union types
Speakeasy
Stainless
Server-sent events
Speakeasy
Stainless
⚠ non-OpenAPI standard
Custom dependency injection
Speakeasy
Stainless

Pricing

In terms of pricing, both Speakeasy and Stainless offer free plans, as well as paid plans for startups and enterprises. The most significant pricing difference is in the enterprise plan. Existing customers indicate that Stainless’s enterprise pricing is ~20% higher than Speakeasy’s. Of course, this can vary, and we recommend reaching out to both companies for a quote.

Pricing Comparison

Plan
Free
Speakeasy
1 free Published SDK
Stainless
1 free local SDK; max 50 endpoints
Scale-Up
Speakeasy
$250/mo/SDK; max 50 endpoints
Stainless
$250/mo/SDK; max 50 endpoints
Business
Speakeasy
$600/mo/SDK; max 200 endpoints
Stainless
$2,500/mo; max 5 SDKs; 150 endpoints
Enterprise
Speakeasy
Custom
Stainless
Custom

Speakeasy vs Stainless: TypeScript SDK comparison

SDK structure

Speakeasy

  • README.md
  • RUNTIMES.md
  • USAGE.md
  • jsr.json
  • package.json
  • tsconfig.json

Stainless

  • Brewfile
  • CONTRIBUTING.md
  • LICENSE
  • README.md
  • SECURITY.md
  • api.md
  • jest.config.ts
  • package.json
  • tsc-multi.json
  • tsconfig.build.json
  • tsconfig.deno.json
  • tsconfig.dist-src.json
  • tsconfig.json
  • yarn.lock

Speakeasy maintains a clear separation of concerns. There are separate folders for models and operations, both in the documentation and in the source folder, and distinct files for each component and operation.

Stainless generates an SDK that, at a glance, looks less organized, considering the greater number of configuration files at the root of the project, no separation of models and operations, and more shims scattered throughout.

Structure might seem superficial at first, but keep in mind that SDK users form their first impressions of your SDK from the same high-level overview. Some of this may be a matter of opinion, but at Speakeasy, we aim to generate SDKs that are as organized as SDKs coded by hand.

Generated types and type safety

Both Speakeasy and Stainless generate TypeScript types, enabling developers to see errors and hints during development. However, Stainless does not generate types for complex OpenAPI component schemas.

For example, consider the following Author component from our OpenAPI document.

The highlighted anyOf list is of particular interest. This list states that a valid Author object must have a name or an id, or both. An author with neither a name nor an id should not validate against this schema.

Let’s take a look at the relevant types generated by each SDK generator:

Here, we see that Speakeasy generates three types for the Author schema: AuthorWithID, AuthorWithName, and a union of these, called Author.

The equivalent type generated by Stainless is an Author interface for each book type, with both id and name marked as optional.

As a result, the following example code using the Stainless SDK will incorrectly compile without any warnings. The equivalent Speakeasy code will correctly catch the compilation error:

Runtime type checking

This brings us to the next type error that should be caught: runtime type errors. Speakeasy creates SDKs that are type-safe from development to production. As our CEO wrote, type safe is better than type faith.

The SDK generated by Speakeasy uses Zod  to validate the data sent to and received from the server. This provides safer runtime code execution and helps developers who use your SDK to receive early feedback about the data their app is sending. Furthermore, data validation on the client side gives users more confidence in your API’s reliability by reducing the opportunity for unintended behavior caused by unexpected data.

To see how this works, let’s look at what happens when the price field (an integer in the Book type from our example) is populated with a float value:

The price field in the Book object in our test code is set to 29.99, which is a floating-point number. This will trigger a Zod validation error before the data is sent to the server, as the price field is expected to be an integer. Handling Zod validation errors  is straightforward, and allows users to get fast feedback on where they are going wrong.

The same book object in code using the Stainless-generated SDK will only be validated on the server. This means that the error will only be caught from the client’s perspective after the data is sent to the server, and the server responds with an error message. If the server is not set up to validate the price field, the error will not be caught at all, leading to unexpected behavior in your users’ applications.

As a result, developers using the SDK generated by Stainless may need to write additional client-side validation code to catch these errors before they are sent to the server.

OAuth client credentials handling

Both Speakeasy and Stainless generate SDKs that handle OAuth 2.0 with client credentials. However, only Speakeasy’s SDKs handle the token lifecycle, retries, and error handling without any additional code.

Our bookstore API requires an OAuth 2.0 token with client credentials to access the API. Let’s see how the SDKs handle this.

Consider the following OAuth 2.0 configuration from our OpenAPI document:

Speakeasy’s generated SDK takes a clientID and clientSecret when instantiating the SDK. The SDK also includes ClientCredentialsHook class that implements BeforeRequestHook to check whether the token is expired and refresh it if necessary. The hook also checks whether the client has the necessary scopes to access the endpoint, and handles authentication errors.

The SDK generated by Stainless requires you to manually fetch and manage the OAuth token. This means that you’ll need to write additional code to handle the token lifecycle, retries, and error handling. You’ll also need to include additional configuration in the Stainless configuration file to use Bearer tokens.

Speakeasy does not require any additional configuration to handle OAuth 2.0 with client credentials. The SDK itself handles the token lifecycle, retries, and error handling.

Webhooks support

Webhooks enable users to receive real-time updates from your API through HTTP callbacks in your SDK. Speakeasy and Stainless both generate SDKs that support webhooks, but Speakeasy’s SDKs provide built-in support for webhook validation, payload parsing, and delivery.

Stainless doesn’t provide out-of-the-box functionality for handling webhooks. You must implement your own logic for verifying event signatures, such as HMAC or RSA, defining event payload types, and managing retry mechanisms.

The example below shows how the techbooks-speakeasy SDK can validate and parse a book.created event, as well as the corresponding OpenAPI spec defining the webhook event.

You can read more about how Speakeasy handles webhooks in our webhooks release post.

React Hooks

React Hooks simplify state and data management in React apps, enabling developers to consume APIs more efficiently. Speakeasy generates built-in React Hooks using TanStack Query . These hooks provide features like intelligent caching, type safety, pagination, and integration with modern React patterns like SSR and Suspense. Stainless does not generate React Hooks.

For example, in this basic implementation, the useQuery hook fetches data from an API endpoint. The cache key ensures unique identification of the query. The status variable provides the current state of the query: loading, error, or success. Depending on the query status, the component renders loading, error, or the fetched data as a list.

For an in-depth look at how Speakeasy uses React Hooks, see our official release article.

Summary

We’ve all experienced bad SDKs that make integration with the API harder, not easier. Speakeasy is building a generator to make poorly written, poorly maintained SDKs a thing of the past. To do so, our team has put an extraordinary level of thought into getting the details of SDK generation right. We think that the effort has earned us the position to compare favorably with any other generator.

If you are interested in seeing how Speakeasy stacks up against some of the popular open-source SDK-generation tools, check out this post.

Last updated on

Organize your
dev universe,

faster and easier.

Try Speakeasy Now