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
sdklabel to be included - Platform compatibility: The method
Specs::getSDKPlatformsForRouteSecurity()(lines 206-224) maps each route's authentication requirements—such asAuthType::SESSIONorAuthType::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:
- Initialize the document structure: Both formatters begin with static top-level objects containing
info,servers, and security definitions (Swagger2.phplines 38-65) - Parse route metadata: The
parse()method (lines 96-376 inOpenAPI3.php) extracts method names, descriptions, consumes/produces content types, andx-appwriteextensions (lines 42-55) - Convert validators to schemas: A comprehensive switch block (lines 94-374) transforms Utopia router validators into OpenAPI parameter definitions and request bodies
- Handle responses: The formatter attaches response models, including
oneOfhandling for union types (lines 66-115) - Generate component schemas: After processing paths, the formatter walks all response models and renders them under
components.schemas(OpenAPI 3) ordefinitions(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:
- Set metadata: A fluent API configures human-readable fields including name, version, repository URLs, share text, and deprecation warnings (lines 75-106)
- Iterate paths and schemas: The generator walks the OpenAPI definition, mapping each path to a client method and each schema to a model class
- Respect extensions: It processes
x-appwriteextensions for platform restrictions, deprecation status, and public visibility - 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:
src/Appwrite/Platform/Tasks/Specs.php: Walks the router and builds Swagger 2/OpenAPI 3 JSON files (lines 31-84)src/Appwrite/SDK/Specification/Format/Swagger2.php: Serializes internal representations into Swagger 2 documents (lines 25-73)src/Appwrite/SDK/Specification/Format/OpenAPI3.php: Serializes the same data to OpenAPI 3 format (lines 24-33)src/Appwrite/Platform/Tasks/SDKs.php: Reads specs, selects languages, and manages Git workflows (lines 31-120)src/Appwrite/SDK/SDK.php: Core generation engine that parses specs and renders language templatessrc/Appwrite/SDK/Language/*: Language-specific configurations and stub templates (e.g.,PHP.php,Node.php)
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.phptask filters routes by platform and security type, then formats them usingSwagger2.phporOpenAPI3.phpvalidators-to-schema converters - SDK generation: The
SDKs.phptask loads JSON specs intoAppwrite\SDK\SDK, which combines the specification with language configurations fromsrc/Appwrite/SDK/Language/to produce complete client libraries - Automation: Both stages are accessible via
php console specsandphp 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →