Services

APIs, CLIs & SDKs

Developer-facing tooling and integrations — clean APIs, first-class CLIs and SDKs, WHMCS and cPanel and beyond.

We build the interfaces other developers and systems talk to: REST APIs, the SDKs and CLIs that wrap them, the webhooks that call back, and the integration glue that makes somebody else's platform behave.

An API is a different kind of deliverable from an application. An application can be refactored on a Tuesday. An API has other people's code written against it, and once a partner has shipped an integration, every response shape is a promise. The decisions that are expensive to reverse — resource naming, error format, what a token is allowed to do, how a caller learns that a four-minute job finished — are all made before the first endpoint goes out.

So the bar is not that it returns 200. It is that a developer can pick it up, run the example straight off the page without editing it, and get the answer the page said they would. Everything below is in service of that.

What you ship when you ship an API.

Six surfaces. The endpoints are the one everybody plans for, and usually the one that causes the least trouble.

The resource model, and the version you cannot take back

An API stops being yours the moment someone integrates against it. Resource names, response shapes, and what a field means under load are decided once and then lived with, so they are worth arguing about before the first endpoint ships rather than in a deprecation notice afterwards.

Vector exposes just over a hundred versioned endpoints across nine groups. Every response shares one envelope, so a client parses one shape, and the errors are predictable enough to program against.

What a token is allowed to do

Authentication is the easy half. The question that decides whether an integration is safe is what a credential can do once it is authenticated — and whether a partner can hand one to a cron job without also handing it the ability to delete production.

Vector issues tokens with abilities scoped per resource and per action, so a partner can mint a key that lists sites but cannot delete them. Rate limits are set by category rather than one global bucket: the calls that cost real infrastructure are throttled hard while read-heavy workflows stay fast. Every query is scoped to the authenticated account, because an unscoped one should be difficult to write by accident.

Work that outlives the request

Provisioning a server, running a migration, building an image — none of it fits inside a request. The design question is not how to make it faster. It is how the caller finds out it finished, and what they are meant to do with a job that has been running for four minutes.

Vector's provisioning API dispatches a job on every endpoint and POSTs a signed callback when it terminates. Helix used four dispatch mechanisms depending on what the caller needed to know: synchronous REST for flat resources, a queue with an HTTP callback for slow lifecycle work, fire-and-forget for anything with nobody waiting, and a pull-based configuration API for the server fleet. More on platforms & hosting and automation & AI workflows.

Webhooks, and proving the call came from you

The API calling the customer back is still the API, and it is the half that gets built last and tested least. It needs a signature the receiver can verify, a retry schedule that gives up eventually, and a delivery log for the afternoon somebody insists the event never arrived.

Vector publishes more than fifty event types, signed HMAC-SHA256 over a timestamped payload and compared in constant time, with a five-minute replay window, exponential backoff to a delivery cap, rotatable secrets, and a queryable delivery history. Inbound callbacks from the build pipeline and the container scheduler are verified the same way.

Documentation that cannot drift

Hand-written API docs are wrong within a quarter. Not through carelessness — the code simply has somewhere else to be. The only reference that stays true is the one generated from the thing it describes.

Vector's reference is generated from the codebase, exported as OpenAPI and Postman, and synced across repositories on every change. It is published on this site at /docs/api/, and the data behind it carries a never-hand-edit contract so nobody can helpfully correct a generated file.

The clients nobody counts as part of the API

SDKs and CLIs get treated as documentation with a build step. They are the API's first real users, and the place its design flaws surface before a customer has to find them.

Vector ships a Go CLI covering the full surface — readable tables in a terminal, clean JSON when piped, credentials in the OS keychain, structured exit codes for scripting — alongside typed Node and PHP SDKs. If the SDK is awkward to use, the API is wrong, and we find out before a partner does.

Generated
the API reference, built from the code it documents
50+
event types a partner can subscribe to
3 clients
a Go CLI and typed Node and PHP SDKs
MCP
the whole API, drivable by an agent

We ship one ourselves, and you can read it.

Vector's API reference is hosted on this site, so the rest of this page does not have to be taken on faith.

Vector is our own product, and API-first in the literal sense. Partners provision and operate WordPress sites entirely through the API and resell the result under their own brand. There is no primary interface that the API is a secondary view of — the API is the interface, and our own CLI and SDKs are built on exactly the surface a partner gets.

The developer-facing half was built as a product rather than a byproduct: token auth with per-resource abilities, rate limits by category, one response envelope, and explicit state machines so an illegal transition is rejected by construction instead of caught afterwards. Around it sit a Go CLI, typed Node and PHP SDKs, and a reference generated from the API itself with an interactive explorer and machine-readable exports. All of it open source.

Most pages like this one ask you to take the claim on trust. This one is a link away from the evidence, so you can go and check whether the auth section really explains scoping, whether the failure cases are documented, and whether the examples would run if you pasted them.

Built so the examples work.

The case for generating documentation from the code is easier to make with a finding than a principle. Porting Vector's reference onto this site regenerated all three hundred and thirty-six code examples and matched the previous output character for character — and turned up defects in the thing it was replacing. Twenty-eight of the published OpenAPI fragments were invalid YAML. A templating bug had been quietly hiding the example value on every boolean parameter. Nobody had noticed, because nobody reads a reference the way a generator does.

The same instinct runs through the rest of it. Versioned envelope schemas and an explicit exit-code taxonomy on the provisioning agent, so a caller can tell a failure apart from a refusal. Documented idempotency semantics for every verb, so a retry is safe by contract rather than by hope. Stable operation IDs, so a generated client does not rename half its methods because an endpoint moved. That is the difference between building an API and building one other systems can depend on.

What we build with

LaravelGoTypeScriptPHPOpenAPIScribePostmanSanctumHMACWHMCScPanelMCP

Three integrations, written up in full.

View all

An API an agent can drive.

The newest part of this, and the part that turned out to be mostly downstream of work we were already doing.

Vector's CLI can register itself as an MCP server, so an assistant can drive the platform — create a site, read logs, roll a deployment — without anyone writing a bespoke integration for it. The reference publishes a plaintext page per endpoint and an index meant to be fetched rather than rendered, so a model reading the docs gets the same content a browser does without the markup wrapped around it.

Worth saying plainly: none of that was the hard part. An API with a real spec, stable operation IDs, documented error shapes, and tokens that scope down to a single action is already most of the way to being drivable by an agent. The MCP server is a thin layer over work that had to happen anyway. When an API is not agent-ready, the fix is usually not an AI project. It is the spec.

WHMCS and cPanel, from the inside.

Two decades in the hosting industry leaves marks. This is one of them.

Hosting companies run on WHMCS and cPanel, and both are easier to fight than to work with. We have built inside them instead. GoCart is a Laravel checkout with no database of its own — two throwaway tables, and everything else lives in WHMCS — talking to a custom addon module through exactly six URLs held in a single class. Adding an endpoint meant a file and a line in a switch, and reading one function told you the complete API.

TurboHub went further: a server module, a provisioning addon, hook chains, and a bidirectional server-to-server OAuth grant so WHMCS could call the platform with the same credential the platform used to call WHMCS — tokens rotating every six hours, and retry loops re-reading the token inside the loop rather than outside it, so a call that started before a rotation still succeeded after it. We also built a database-backed job queue inside WHMCS, with tests, which is rarer than it ought to be. The rule on both was the same: never query the WHMCS database, only its API.

The same work applies when the job is getting out — extracting a service from a monolith, or keeping an old system and a new one in agreement while both are live and customers are on each.

If you are exposing an API, shipping a CLI or an SDK, or trying to make two systems that were never meant to meet agree on something, we have probably met the problem before.