Background image

In Depth: Speakeasy vs APIMatic

Nolan Sullivan

Nolan Sullivan

April 17, 2025

Featured blog post image

At Speakeasy, we create idiomatic SDKs in the most popular languages. Our generators follow principles that ensure we create SDKs that offer the best developer experience so that you can focus on building your API, and your developer-users can focus on delighting their users.

In this post, we’ll compare TypeScript SDKs created by Speakeasy to those generated by APIMatic.

SDK Generation Targets

At Speakeasy, we believe it is crucial to meet your users where they are by supporting SDKs in languages your users depend on. Anyone who has had to maintain custom SDK code because a vendor doesn’t support their tech stack knows how frustrating this can be.

This table shows the current, as of September 2024, languages and platforms targeted by Speakeasy and APIMatic. These lists will change over time, so check the official documentation for the latest language support.

LanguageSpeakeasyAPIMatic
Python
TypeScript
Go✅ (Alpha)
C# (.NET)
PHP
Ruby
Java
Kotlin⚠ Java is Kotlin-compatible
Terraform provider
Swift
Unity
Postman Collection

We’re always open to expanding our language support, but would only ever do this if we have the in-house experience to create idiomatic, best-in-class SDKs for a given language. Let us know if you would like to suggest a language or platform to support.

SDK Features

The table below compares the current SDK features offered by Speakeasy and APIMatic as of September 2024. Both Speakeasy and APIMatic are under active development, so these features may change over time.

FeatureSpeakeasyAPIMatic
Union types
Discriminated union types⚠ non-OpenAPI standard
Server-sent events
Retries
Pagination
Async support
Streaming uploads
OAuth 2.0
Custom SDK naming
Customize SDK structure
Custom dependency injection

APIMatic lacks advanced SDK customization features, and we couldn’t find any code or documentation related to pagination. These are features Speakeasy’s users rely on.

Platform Features

Speakeasy’s primary interface is an open-source, full-featured, and portable CLI. Developers use our CLI to experiment and iterate locally and to customize their CI/CD workflows.

APIMatic’s CLI depends on Node.js and several packages. This makes it much less portable. In testing, we also found that it does not generate SDKs as reliably as the APIMatic web interface.

FeatureSpeakeasyAPIMatic
GitHub CI/CD
CLI
Web interface
Package publishing
OpenAPI linting
Documentation generation
Test generation
OpenAPI overlays
Change detection
Developer portal

Enterprise Support

Both Speakeasy and APIMatic offer support for Enterprise customers. This includes features like concierge onboarding, private Slack channels, and enterprise SLAs.

FeatureSpeakeasyAPIMatic
Concierge onboarding
Private Slack channel
Enterprise SLAs
User issues triage

Pricing

Speakeasy offers a free plan, while APIMatic offers a limited free trial.

PlanSpeakeasyAPIMatic
Free1 free Published SDK, 50 endpointsTrial only
Startup1 free + $250/mo/SDK, 50 endpoints eachN/A
Lite: StarterN/A$15/mo. 1 API, 10 endpoints, no team members.
Lite: BasicN/ACustom. 1 API, 20 endpoints, 2 team members.
BusinessN/ACustom. Up to 50 APIs, 100 endpoints each, 15 team members.
EnterpriseCustomCustom

Speakeasy’s free plan is more generous than both Lite plans offered by APIMatic.

Speakeasy vs APIMatic Technical Walkthrough

Dependencies and SBOM (Software Bill of Materials)

CompanyTotal dependenciesUnmaintained dependenciesSupply chain risks
Speakeasy100
ApiMatic4174

From day one, Speakeasy has prioritized efficiency, and we’ve kept the dependency trees for our generated SDKs as lean as possible. For example, here’s the dependency graph for the Vercel SDK (opens in a new tab), an SDK generated by Speakeasy. It has zero direct dependencies, and one peer dependency (Zod).

Vercel dependency graph

By contrast, here’s the dependency graph for the Maxio SDK (opens in a new tab), an SDK generated by APIMatic. It has many dependencies, which in turn have transitive dependencies, leading to a much more bloated SDK that is harder to maintain.

Maxio dependency graph

Having more dependencies isn’t only bad in terms of efficiency. Many libraries single or no active maintainer. Many dependencies also have unaddressed critical vulnerabilities (CVs), leaving the upstream SDK vulnerable as well (the Maxio SDK has 4 of these (opens in a new tab)).

Bundle size

CompanyBundle size
Speakeasy124.1 kb
ApiMatic358.1 kb

Dependencies aren’t just a security risk. They also bloat the size of your SDK. Here’s a comparison of the bundle sizes for libraries generated from the same OpenAPI spec by Speakeasy and APIMatic:

Speakeasy Bundle Size

APIMatic Bundle Size

That bundle size is a problem if you have customers that need to integrate with your API in runtimes where performance is critical (browser and on the edge).

Type safety

Speakeasy creates SDKs that are type-safe from development to production. As our CEO recently wrote, Type Safe is better than Type Faith.

Speakeasy uses Zod (opens in a new tab) to validate data at runtime. Data sent to the server and data received from the server are validated against Zod definitions in the client.

This provides safer runtime code execution and helps developers who use your SDK to provide early feedback about data entered by their end users. Furthermore, trusting data validation on the client side allows developers more confidence to build optimistic UIs (opens in a new tab) that update as soon as an end user enters data, greatly improving end users’ perception of your API’s speed.

APIMatic 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.

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

Discriminated Unions

Our OpenAPI document includes a Book component with a category field that can be one of three values: Programming, Fantasy, or SciFi.

This allows us to type the Book component in requests and responses as specific book types, such as ProgrammingBook, FantasyBook, and SciFiBook.

OpenAPI supports discriminated unions using the discriminator field in the schema. Here’s an example of a response that returns an array of books of different types:

openapi.yaml
schema:
type: array
items:
oneOf:
- $ref: "#/components/schemas/ProgrammingBook"
- $ref: "#/components/schemas/FantasyBook"
- $ref: "#/components/schemas/SciFiBook"
discriminator:
propertyName: category
mapping:
Programming: "#/components/schemas/ProgrammingBook"
Fantasy: "#/components/schemas/FantasyBook"
Sci-fi: "#/components/schemas/SciFiBook"

Let’s see how the SDKs handle this.

Speakeasy generates TypeScript types for each book type, and uses a discriminated union to handle the different book types. This enables developers to use the correct type when working with books of different categories. This pattern could just as easily apply to payment methods or delivery options.

The example below shows how Speakeasy defines the ProgrammingBook type. It also generates types for FantasyBook and SciFiBook.

In this example, you’ll notice that the category field is optional in the ProgrammingBook type, but is enforced by Zod validation in the SDK.

speakeasy/books.ts
/*
* Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.
*/
import { Author, Author$ } from "./author";
import * as z from "zod";
export type ProgrammingBook = {
id?: number | undefined;
title: string;
description: string;
/**
* Price in USD cents
*/
price: number;
category?: "Programming" | undefined;
author: Author;
coverImage?: string | undefined;
};
/** @internal */
export namespace ProgrammingBook$ {
export const inboundSchema: z.ZodType<ProgrammingBook, z.ZodTypeDef, unknown> = z
.object({
id: z.number().int().optional(),
title: z.string(),
description: z.string(),
price: z.number().int(),
category: z.literal("Programming").optional(),
author: Author$.inboundSchema,
cover_image: z.string().optional(),
})
.transform((v) => {
return {
...(v.id === undefined ? null : { id: v.id }),
title: v.title,
description: v.description,
price: v.price,
...(v.category === undefined ? null : { category: v.category }),
author: v.author,
...(v.cover_image === undefined ? null : { coverImage: v.cover_image }),
};
});
export type Outbound = {
id?: number | undefined;
title: string;
description: string;
price: number;
category: "Programming";
author: Author$.Outbound;
cover_image?: string | undefined;
};
export const outboundSchema: z.ZodType<Outbound, z.ZodTypeDef, ProgrammingBook> = z
.object({
id: z.number().int().optional(),
title: z.string(),
description: z.string(),
price: z.number().int(),
category: z.literal("Programming").default("Programming" as const),
author: Author$.outboundSchema,
coverImage: z.string().optional(),
})
.transform((v) => {
return {
...(v.id === undefined ? null : { id: v.id }),
title: v.title,
description: v.description,
price: v.price,
category: v.category,
author: v.author,
...(v.coverImage === undefined ? null : { cover_image: v.coverImage }),
};
});
}

We can see how Speakeasy generates SDK code to handle the different book types in the response for the getgetAllBooks operation:

speakeasy/getallbooks.ts
/*
* Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.
*/
import * as components from "../components";
import * as z from "zod";
export type ResponseBody =
| (components.ProgrammingBook & { category: "Programming" })
| (components.FantasyBook & { category: "Fantasy" })
| (components.SciFiBook & { category: "Sci-fi" });
export type GetAllBooksResponse = {
httpMeta: components.HTTPMetadata;
/**
* A list of books
*/
responseBodies?:
| Array<
| (components.ProgrammingBook & { category: "Programming" })
| (components.FantasyBook & { category: "Fantasy" })
| (components.SciFiBook & { category: "Sci-fi" })
>
| undefined;
};
// ...

Note how the array elements in responseBodies are typed according to the book category.

This may seem like a trivial example, but it illustrates how Speakeasy generates types that are more specific and easier to work with than the types generated by APIMatic. This could, for instance, help developers correctly handle different book types in their applications.

APIMatic does not generate types for discriminated unions, and developers must manually handle the different book types in the response.

Here is the equivalent type definition generated by APIMatic:

apimatic/programmingBook.ts
/**
* Bookstore APILib
*
* This file was automatically generated by APIMATIC v3.0 ( https://www.apimatic.io ).
*/
// ...
import { CategoryEnum, categoryEnumSchema } from './categoryEnum';
// ...
export interface ProgrammingBook {
id?: number;
title: string;
description: string;
/** Price in USD cents */
price: number;
category: CategoryEnum;
author: Author2;
coverImage?: string;
}
// ...

Following the CategoryEnum import:

apimatic/categoryEnum.ts
/**
* Bookstore APILib
*
* This file was automatically generated by APIMATIC v3.0 ( https://www.apimatic.io ).
*/
// ...
/**
* Enum for CategoryEnum
*/
export enum CategoryEnum {
Scifi = 'Sci-fi',
Fantasy = 'Fantasy',
Programming = 'Programming',
}
// ...

Discriminating between different book types in the response is left to users.

Speakeasy Compared to Open-Source Generators

If you are interested in seeing how Speakeasy stacks up against other SDK generation tools, check out our post.

CTA background illustrations

Speakeasy Changelog

Subscribe to stay up-to-date on Speakeasy news and feature releases.