Upsun official PHP SDK
The open-source PHP client for the Upsun API: generated from the OpenAPI spec, with a handwritten developer-facing layer.
- Role
- Development, in the Advocacy team: full API coverage, facades, tests, release
- Period
- Jul 2025 – ongoing · Upsun
- Stack
- PHP 8.1+
- OpenAPI Generator
- Mustache
- PHPUnit
- GitHub Actions
- Composer
Context
The Upsun API is rich (organizations, projects, environments, variables, deployments…), but calling it from PHP meant writing HTTP requests, authentication and models yourself. It needed an official, complete SDK that stays current with no effort as the API evolves.
What I built
Starting from the initial skeleton set up by an Advocacy teammate, I built most of the SDK: full API coverage, the facades, the tests and the Packagist release. The architecture has two layers:
- A generated layer built with OpenAPI Generator from the official OpenAPI spec, served by Meta-Upsun: one model per schema, one class per endpoint group. It covers 100% of the public API.
- A handwritten "Tasks" layer, the public interface:
$client->projects->create(...),$client->organizations->listProjects(...), with named arguments, strict types andreadonlyproperties. Developers never touch the generated models.
Around it:
- Spec pre-processing in PHP before generation: Mustache templates only handle simple tests, so transformations (adding
x-*fields, fixes) happen upstream, in testable code. - Daily sync: a GitHub workflow compares the published spec with the local copy and opens a pull request when they differ.
- Alignment with the Node.js SDK: same method names and signatures, enforced by a checking tool I wrote that reports any divergence between the two SDKs.
- 476 PHPUnit tests (over 3,500 assertions) and full PHPDoc for IDE autocompletion.
- Distributed on Packagist:
composer require upsun/upsun-sdk-php. Source code on GitHub. - Searchable documentation of the architecture and code on DeepWiki.
Technical challenges
- A real-world spec is never perfect: incomplete schemas, ambiguous types. Pre-processing fixes them without touching the official source, and every fix is versioned.
- Separating generated from maintained code: the Tasks layer shields users from changes in the generated code. An API change doesn't break their code.
Results
- An official, open-source SDK, published on Packagist and documented.
- Signatures consistent with the Node.js SDK, and an approach planned for Python and Go.
