How Appwrite Generates SDKs from OpenAPI and Swagger Specifications: A Complete Technical Guide

Appwrite generates SDKs by first converting its internal route definitions into Swagger 2 or OpenAPI 3 JSON specifications, then feeding those specifications into a language-specific template engine that renders client libraries for PHP, Node.js, Dart, and other platforms.

The appwrite/appwrite repository contains a sophisticated two-stage pipeline that automates the creation of type-safe client libraries directly from the server's routing layer. This approach ensures that every SDK remains perfectly synchronized with the latest API changes without manual maintenance. Understanding this architecture reveals how Appwrite maintains nine official SDKs across multiple languages while guaranteeing API consistency.

Specification Generation: From Appwrite Routes to OpenAPI Documents

The first stage of the pipeline creates machine-readable API descriptions. Located in src/Appwrite/Platform/Tasks/Specs.php, this console task walks through every registered route in the Appwrite router and emits standardized Swagger 2 or OpenAPI 3 JSON files.

Collecting Routes and Filtering by Platform

The generation process begins by retrieving all application routes via App::getRoutes() (line 29 in Specs.php). However, not every internal route appears in the public SDKs. The system filters routes based on two criteria:

  • SDK visibility: Routes must expose an sdk label to be included
  • Platform compatibility: The method Specs::getSDKPlatformsForRouteSecurity() (lines 206-224) maps each route's authentication requirements—such as AuthType::SESSION or AuthType::KEY—to three supported platforms: client, server, or console

Only routes matching the target platform and containing SDK metadata proceed to the formatting stage.

Formatting as Swagger 2 and OpenAPI 3

Once filtered, routes pass to specialized formatters: Swagger2.php or OpenAPI3.php (both located in src/Appwrite/SDK/Specification/Format/). These classes convert Appwrite's internal route definitions into standard specifications through the following process:

  1. Initialize the document structure: Both formatters begin with static top-level objects containing info, servers, and security definitions (Swagger2.php lines 38-65)
  2. Parse route metadata: The parse() method (lines 96-376 in OpenAPI3.php) extracts method names, descriptions, consumes/produces content types, and x-appwrite extensions (lines 42-55)
  3. Convert validators to schemas: A comprehensive switch block (lines 94-374) transforms Utopia router validators into OpenAPI parameter definitions and request bodies
  4. Handle responses: The formatter attaches response models, including oneOf handling for union types (lines 66-115)
  5. Generate component schemas: After processing paths, the formatter walks all response models and renders them under components.schemas (OpenAPI 3) or definitions (Swagger 2) (lines 379-496)

The resulting JSON files—stored in app/config/specs/—serve as the single source of truth for all SDK generation.

SDK Generation: Converting Specifications into Language-Specific Code

The second stage transforms these JSON specifications into complete, publishable SDKs. The SDKs.php task (located in src/Appwrite/Platform/Tasks/) orchestrates this conversion by combining the specification with language-specific templates.

Loading Specifications and Configuring Languages

The process starts by loading the previously generated specification file:

php console sdks --platform=client --sdk=php --version=1.2.0

Internally, SDKs.php reads the JSON specification (line 28):

$spec = file_get_contents(__DIR__.'/../../../../app/config/specs/swagger2-' . $version . '-' . $language['family'] . '.json');

Based on the --sdk parameter, the system instantiates a language configuration object through a switch block (lines 57-115). For example, selecting php creates an instance of Appwrite\SDK\Language\PHP, while nodejs instantiates the Node configuration. These objects hold package metadata, dependency managers (Composer, NPM, Bower), and licensing information.

The Core Generation Engine

With the specification loaded and language configured, the system creates the generator instance (line 73):

$sdk = new SDK($config, new Swagger2($spec));

The Appwrite\SDK\SDK class (located in src/Appwrite/SDK/SDK.php) serves as the core templating engine. It accepts the language configuration and a specification formatter, then processes the API description through the following steps:

  1. Set metadata: A fluent API configures human-readable fields including name, version, repository URLs, share text, and deprecation warnings (lines 75-106)
  2. Iterate paths and schemas: The generator walks the OpenAPI definition, mapping each path to a client method and each schema to a model class
  3. Respect extensions: It processes x-appwrite extensions for platform restrictions, deprecation status, and public visibility
  4. Render templates: Using stub files located in src/Appwrite/SDK/Language/*/, it generates API client classes, helper utilities, documentation (README.md, GETTING_STARTED.md), and usage examples

Finally, SDK::generate($outputDir) (line 112) writes the complete SDK to the specified output directory.

Practical Usage and CLI Commands

The entire pipeline is accessible through two console commands. To generate a specification for the latest version:

php console specs --version=latest --mode=normal

# Creates: app/config/specs/swagger2-latest-client.json

To generate the PHP SDK from that specification:

php console sdks --platform=client --sdk=php --version=latest

# Output: app/sdks/client-php/

For a Node.js server SDK with Git integration (dry-run):

php console sdks \
    --platform=server \
    --sdk=nodejs \
    --version=1.4.x \
    --git=yes \
    --production=no \
    --message="Update Node SDK for 1.4.x" \
    --release=no \
    --commit=no

Programmatic SDK Generation

You can bypass the CLI and use the SDK generator programmatically for custom specifications:

<?php
require __DIR__.'/vendor/autoload.php';

use Appwrite\SDK\SDK;
use Appwrite\SDK\Language\PHP;
use Appwrite\SDK\Specification\Format\Swagger2;

$specJson = file_get_contents('custom-spec.json');
$config = (new PHP())
    ->setComposerVendor('myorg')
    ->setComposerPackage('my-sdk');

$sdk = new SDK($config, new Swagger2($specJson));
$sdk->setName('My Custom SDK')
    ->setVersion('0.1.0')
    ->generate(__DIR__.'/output');

Key Source Files and Architecture

Understanding the repository structure clarifies how the pipeline operates:

Summary

  • Two-stage pipeline: Appwrite first generates OpenAPI/Swagger specifications from internal routes, then uses those specifications to render SDKs through language-specific templates
  • Specification generation: The Specs.php task filters routes by platform and security type, then formats them using Swagger2.php or OpenAPI3.php validators-to-schema converters
  • SDK generation: The SDKs.php task loads JSON specs into Appwrite\SDK\SDK, which combines the specification with language configurations from src/Appwrite/SDK/Language/ to produce complete client libraries
  • Automation: Both stages are accessible via php console specs and php console sdks, enabling automated SDK releases that perfectly mirror the server API

Frequently Asked Questions

What is the difference between the Specs task and the SDKs task in Appwrite?

The Specs task (console specs) generates intermediate API description files (Swagger 2 or OpenAPI 3 JSON) by introspecting the Appwrite router. The SDKs task (console sdks) consumes those JSON files and produces actual source code in languages like PHP, Node.js, or Dart. You must run the Specs task first to create the specification that the SDKs task requires.

Which OpenAPI versions does Appwrite support for SDK generation?

According to the source code in src/Appwrite/SDK/Specification/Format/, Appwrite supports both Swagger 2.0 and OpenAPI 3.0.x specifications. The Specs.php task can emit either format, and the SDK.php generator accepts both Swagger2 and OpenAPI3 formatter objects as input sources.

How does Appwrite handle authentication when generating SDKs?

During specification generation, Specs::getSDKPlatformsForRouteSecurity() (lines 206-224) analyzes each route's authentication requirements and maps them to appropriate platforms (client, server, or console). The resulting specification includes securityDefinitions or securitySchemes that the SDK generator translates into language-specific authentication helpers, ensuring that generated clients properly handle API keys, JWT tokens, or session-based auth.

Can I customize the generated SDKs for my own organization?

Yes. You can programmatically instantiate the Appwrite\SDK\SDK class with a custom Appwrite\SDK\Language\* configuration object. By setting vendor names, package identifiers, and repository URLs through the fluent API (methods like setComposerVendor() or setNPMPackage()), you can generate SDKs branded for your organization while maintaining compatibility with the Appwrite API specification.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →