Comparison

Generated 2026-05-26

SDK Parity vs SDK generation platforms.

A generated side-by-side view of SDK Parity against Fern, OpenAPI Generator, Kiota, Hey API, Stainless, and Speakeasy. Local providers are run against the same fixture; account-gated providers stay source-backed until credentials are connected.

Fixture operations1414 schemas
Local provider runs5same OpenAPI fixture
Account-gated platforms2Stainless, Speakeasy
SDK Parity generation<100 msfull target set

SDK Parity

Generated

Measured from the generated comparison fixture.

Fern

Generated

Generated locally with Fern self-hosted SDK generation for TypeScript, Python, Go, Rust, Java, C#, Ruby, and PHP.

OpenAPI Generator

Generated

Generated locally with OpenAPI Generator Docker clients for TypeScript Fetch and Python.

Kiota

Generated

Generated locally with Kiota Docker fluent request builders for TypeScript and Python.

Hey API

Generated

Generated locally with Hey API openapi-ts for a TypeScript fetch client.

Stainless

Account auth

Account-gated hosted SDK platform with SDKs, docs, CLI, MCP, Terraform, and enterprise controls in public docs.

Speakeasy

Account auth

Account-gated SDK and MCP platform with language generators, contract tests, managed workflows, and AI control-plane products in public docs.

Feature matrix

What the fixture proves today, with account-gated claims kept source-bound.

SDK and platform features
SDK Parity and Fern cells are generated from local fixture output. Stainless and Speakeasy cells are backed by public docs and account-gated CLI flows.

Scroll to compare.

FeatureSDK ParityStainlessSpeakeasyFern
TypeScript SDKGeneratedDocumented/account-gatedDocumented/account-gatedGenerated
Python SDKGeneratedDocumented/account-gatedDocumented/account-gatedGenerated
Mainstream language breadthGeneratedDocumented/account-gatedDocumented/account-gatedGenerated
Auto-pagination helpersGeneratedDocumented/account-gatedDocumented/account-gatedNot generated
Retries, idempotency, and local rate limitingGeneratedDocumented/account-gatedDocumented/account-gatedGenerated
Strict request/response validationGeneratedDesign decision: no runtime request validationDocumented/account-gatedNot generated
Streaming responsesGeneratedDocumented/account-gatedDocumented/account-gatedGenerated
Custom code preservationGeneratedDocumented/account-gatedDocumented/account-gatedDocumented/account-gated
Generated docs and snippetsGeneratedDocumented/account-gatedDocumented/account-gatedGenerated
MCP / Code ModeGeneratedDocumented/account-gatedDocumented/account-gatedDocs MCP documented
Independent SDK surface manifest and compatibility diffCore wedgeNot centeredPartialPartial

Local provider numbers are generated from the comparison fixture in this build.

Stainless and Speakeasy are source-backed account-gated integrations, not local artifact runs in this repo.

Benchmark values are generation-time and footprint evidence, not live API latency claims.

Benchmark matrix
Generation time and footprint from the same dogfood OpenAPI document.

Scroll to compare.

MetricSDK ParityFernOpenAPI GeneratorKiotaHey API
Generation time for same-spec fixture<100 ms84.5 s7.9 s35.9 s100-500 ms
TypeScript generated footprint26 files / 3737 LOC / 148 KB141 files / 4778 LOC / 166 KB35 files / 3547 LOC / 103 KB24 files / 2337 LOC / 103 KB16 files / 2489 LOC / 69 KB
Python generated footprint27 files / 4397 LOC / 228 KB89 files / 8922 LOC / 282 KB40 files / 8608 LOC / 301 KB54 files / 3075 LOC / 135 KBNot targeted
Mainstream generated footprint21 files / 736 LOC / 22 KB634 files / 72098 LOC / 2.0 MB652 files / 86679 LOC / 2.7 MB314 files / 23415 LOC / 1.0 MBNot targeted
Docs/reference generated footprint16 files / 3297 LOC / 83 KB1 files / 937 LOC / 12 KB62 files / 3804 LOC / 105 KBNot targetedNot targeted
Non-SDK release/agent artifacts17 files / 7408 LOC / 214 KBNot targetedNot targetedNot targetedNot targeted
Artifact footprint
Generated from the current comparison fixture.
  • SDK Parity107 files
    19575 LOC696 KB
    typescript: 26python: 27go: 4rust: 3
  • Fern865 files
    86735 LOC2.5 MB
    typescript: 141python: 89go: 92rust: 80
  • OpenAPI Generator791 files
    102753 LOC3.2 MB
    typescript: 35python: 40go: 87rust: 74
  • Kiota392 files
    28827 LOC1.2 MB
    typescript: 24python: 54go: 57java: 54
  • Hey API16 files
    2489 LOC69 KB
    typescript: 16

SDK code shape

Compare SDK Parity beside each provider, language by language.

Language

Compare against

SDK Parity baseline

SDK Parity

Generated TypeScript client

Generated artifact
export class SDKParityClient {
  readonly apiKey: string | null;
  readonly username: string | null;
  readonly password: string | null;
  readonly oauthClientId: string | null;
  readonly oauthClientSecret: string | null;
  readonly oauthTokenUrl: string | null;
  readonly oauthScopes: string[];
  readonly baseURL: string;
  readonly timeoutMs: number;
  readonly maxRetries: number;
  readonly retryBackoff: Required<RetryBackoffConfig>;
  readonly defaultHeaders: Record<string, string | undefined>;
  readonly idempotency: Required<IdempotencyConfig> | false;
  readonly strictRequestValidation: boolean;
  readonly strictResponseValidation: boolean;
  readonly hooks: SDKEventHooks;
  private readonly accessTokenProvider?: () => string | Promise<string>;
  private readonly fetchImpl: typeof globalThis.fetch;
  private readonly limiter?: RateLimiter;
  private readonly operationLimiters = new Map<string, RateLimiter>();
  private oauthToken?: { accessToken: string; expiresAt: number };
  readonly artifacts: ArtifactsResource;
  readonly codeMode: CodeModeResource;
  readonly configs: ConfigsResource;
  readonly docs: DocsResource;
  readonly jobs: GeneratorJobsResource;
  readonly mcp: McpResource;
  readonly migration: MigrationResource;
  readonly openapi: OpenapiResource;
  readonly previewBuilds: PreviewBuildsResource;
  readonly releaseWorkflows: ReleaseWorkflowsResource;

  constructor(options: ClientOptions = {}) {
    const apiKey = options.apiKey ?? readEnv("SDKPARITY_API_KEY") ?? null;
    const username = options.username ?? readEnv("SDKPARITY_USERNAME") ?? null;
    const password = options.password ?? readEnv("SDKPARITY_PASSWORD") ?? null;
    const oauthClientId = options.oauthClientId ?? readEnv("SDKPARITY_OAUTH_CLIENT_ID") ?? null;
    const oauthClientSecret = options.oauthClientSecret ?? readEnv("SDKPARITY_OAUTH_CLIENT_SECRET") ?? null;
    if (!options.dangerouslyAllowBrowser && isBrowser() && (apiKey || options.accessTokenProvider || username || password || oauthClientId || oauthClientSecret)) {
      throw new APIError('Refusing to run with secret credentials in a browser. Pass dangerouslyAllowBrowser only if your credential model is safe for browsers.');
    }
    if (!apiKey && !options.accessTokenProvider && (!oauthClientId || !oauthClientSecret)) throw new APIError('Missing credentials. Pass apiKey, accessTokenProvider, OAuth client credentials, or set SDKPARITY_API_KEY.');

    this.apiKey = apiKey;
    this.username = username;
    this.password = password;
    this.oauthClientId = oauthClientId;
    this.oauthClientSecret = oauthClientSecret;
    this.oauthTokenUrl = options.oauthTokenUrl ?? null;
    this.oauthScopes = options.oauthScopes ?? [];
    this.baseURL = stripTrailingSlash(options.baseURL ?? environmentURL(options.environment) ?? "https://api.sdkparity.example/v1");
    this.timeoutMs = options.timeoutMs ?? 60000;
    this.maxRetries = options.maxRetries ?? 2;
    this.retryBackoff = resolveRetryBackoff(options.retryBackoff, {"initialDelayMs":500,"maxDelayMs":8000,"maxElapsedMs":60000,"multiplier":2,"jitter":0.25});
    this.defaultHeaders = options.defaultHeaders ?? {};
    this.fetchImpl = options.fetch ?? globalThis.fetch;
    this.accessTokenProvider = options.accessTokenProvider;
    this.strictRequestValidation = options.strictRequestValidation ?? false;
    this.strictResponseValidation = options.strictResponseValidation ?? false;
    this.hooks = options.hooks ?? {};
    this.idempotency =
      options.idempotency === false
        ? false

Provider comparison

Fern

Generated TypeScript client

Generated artifact
// This file was auto-generated by Fern from our API Definition.

import { ArtifactsClient } from "./api/resources/artifacts/client/Client.js";
import { CodeModeClient } from "./api/resources/codeMode/client/Client.js";
import { ConfigsClient } from "./api/resources/configs/client/Client.js";
import { DocsClient } from "./api/resources/docs/client/Client.js";
import { GeneratorJobsClient } from "./api/resources/generatorJobs/client/Client.js";
import { McpClient } from "./api/resources/mcp/client/Client.js";
import { MigrationClient } from "./api/resources/migration/client/Client.js";
import { OpenapiClient } from "./api/resources/openapi/client/Client.js";
import { PreviewBuildsClient } from "./api/resources/previewBuilds/client/Client.js";
import { ReleaseWorkflowsClient } from "./api/resources/releaseWorkflows/client/Client.js";
import type { BaseClientOptions, BaseRequestOptions } from "./BaseClient.js";
import { type NormalizedClientOptionsWithAuth, normalizeClientOptionsWithAuth } from "./BaseClient.js";
import * as core from "./core/index.js";

export declare namespace SdkparityApiClient {
    export type Options = BaseClientOptions;

    export interface RequestOptions extends BaseRequestOptions {}
}

export class SdkparityApiClient {
    protected readonly _options: NormalizedClientOptionsWithAuth<SdkparityApiClient.Options>;
    protected _configs: ConfigsClient | undefined;
    protected _openapi: OpenapiClient | undefined;
    protected _generatorJobs: GeneratorJobsClient | undefined;
    protected _previewBuilds: PreviewBuildsClient | undefined;
    protected _artifacts: ArtifactsClient | undefined;
    protected _docs: DocsClient | undefined;
    protected _mcp: McpClient | undefined;
    protected _codeMode: CodeModeClient | undefined;
    protected _migration: MigrationClient | undefined;
    protected _releaseWorkflows: ReleaseWorkflowsClient | undefined;

    constructor(options: SdkparityApiClient.Options) {
        this._options = normalizeClientOptionsWithAuth(options);
    }

    public get configs(): ConfigsClient {
        return (this._configs ??= new ConfigsClient(this._options));
    }

    public get openapi(): OpenapiClient {
        return (this._openapi ??= new OpenapiClient(this._options));
    }

    public get generatorJobs(): GeneratorJobsClient {
        return (this._generatorJobs ??= new GeneratorJobsClient(this._options));
    }

    public get previewBuilds(): PreviewBuildsClient {
        return (this._previewBuilds ??= new PreviewBuildsClient(this._options));
    }

    public get artifacts(): ArtifactsClient {
        return (this._artifacts ??= new ArtifactsClient(this._options));
    }

    public get docs(): DocsClient {
        return (this._docs ??= new DocsClient(this._options));
    }

    public get mcp(): McpClient {
Integration status
Commercial providers are separated by the access needed to reproduce their runs.
  • StainlessAccount auth required

    GitHub-backed Stainless account, organization, and project workspace.

    stl auth login -> stl init -> stl preview

  • SpeakeasyAccount auth required

    Speakeasy workspace login or SPEAKEASY_API_KEY for CI generation.

    speakeasy auth login -> speakeasy quickstart

  • Fern cloudLocal SDKs generated

    Docker for local self-hosted generation; Fern account for cloud publishing workflows.

    fern generate --group local --local