For developers

Hosting you can drive from code

Zinn Digital® is an API-first platform. The same engine API that powers our dashboard is the one you get — versioned, spec-first and 100% documented at build time, with generated SDKs, a CLI, a Terraform provider, signed webhooks and an MCP server on top of it. Whatever you use to work — a terminal, a pipeline, a state file or an AI agent — the platform answers to it.

  • 100,000+PBN sites hosted across every niche
  • 1OpenAPI spec every tool is generated from
  • 4client SDKs — TypeScript, Python, PHP, Go
  • OAuth 2.1scoped, revocable AI-agent access

One API. Every surface rides it.

Most hosts bolt an API onto a control panel after the fact, and it shows — half the panel's features never make it out. We built the other way round. The dashboard, the admin console, the CLI, the Terraform provider, the MCP server and your own integrations all consume the same engine API. If you can do it in the panel, you can do it in code.

Spec-first, not documented later

The OpenAPI spec is the source of truth, and no endpoint ships unless it is in the spec. That single rule is what makes the public API fully documented at build time rather than eventually — there is no undocumented corner, because an undocumented endpoint cannot exist.

Generated, never hand-maintained

Interactive reference docs, the four client SDKs, much of the CLI and the Terraform provider scaffolding are all generated from that one spec. One source, many artefacts, always in sync — you never chase a doc that drifted away from the implementation.

Versioned with a deprecation policy

Endpoints live under /v1 with a published deprecation policy and a changelog. You get told before something changes, in writing, rather than discovering it from a failing build.

Contract-tested in CI

Implementation-versus-spec contract tests and OpenAPI linting run on every change. Drift between the code and the contract fails the build — so the spec you generate your client from is the spec the server actually honours.

Auth, scoping and the things that bite at scale

Two ways in, one uniform principal behind them. Whichever you use, the same permission checks and the same database-level isolation apply.

API keys, per organisation

Keys look like zdk_<mode>_<prefix>_<secret>. Only a SHA-256 hash of the secret is stored — we cannot show you a key again after issue, and neither can anyone who reaches our database. Keys carry scopes, can be revoked, and are issued per organisation rather than per person.

Live and test modes, kept apart

Sandbox keys are separate from production keys and run against sandbox mode: no real billing, no real provisioning. Your integration tests can hammer the API without spending money or building servers.

OIDC for humans

User sessions authenticate with Keycloak-issued JWTs, verified against the realm public key, and resolve to the same Principal object an API key does. Endpoints gate on granular permission keys such as sites.create or apikeys.manage, checked per organisation — holding a permission in one org grants nothing in another.

Row-level security underneath

Every tenant request runs in a transaction with the Postgres org scope set from the principal, so isolation is enforced by the database, not by an ORM filter someone might forget. The queryset filter is still there as defence in depth.

Built for machines, not just for demos

An API is easy to make look good in a README and hard to make behave under real traffic. These are the parts we sweated, because they are the parts that break integrations at three in the morning.

One detail worth calling out, because it shapes how bulk work behaves: a 409 on duplicate domain answers "is this hostname hosted here?" for any tenant, which is an enumeration oracle and a real deanonymisation risk against Footprint-Free. Throttling site creation would have been the lazy fix and would have broken the bulk-provisioning product outright. Instead only rejected duplicate-domain attempts are budgeted, per principal. Successful creates are never charged against it — so you can provision in bulk all day, and probing dies almost immediately.

  • A consistent error envelope on every failure: a code, a human message, optional field-level details and a request_id you can quote to support. Validation errors return 422 with the offending fields named.
  • Idempotency keys on POST, with the replay record written on commit rather than inline — so a retry can never replay a cached 201 that names a row which never committed. A failed request releases its in-flight lock immediately, so a 422 does not lock out your corrected retry.
  • Cursor pagination as keyset over UUIDv7 — stable under concurrent writes, with no page-drift when rows are inserted mid-scan.
  • RateLimit-Remaining on responses, so a generated client can back off intelligently instead of guessing.
  • Out-of-scope resources return 404, never 403 — a 403 would confirm the resource exists. Filtering by an organisation outside your scope returns an empty page for the same reason.
  • Site creation is registration, not provisioning: POST /v1/sites returns 201 with status pending and never blocks on the build. The event is written to the transactional outbox in the same transaction as the row, so a site exists if and only if its provisioning is guaranteed to be requested.

SDKs, a CLI and a Terraform provider

Three consumers of the same spec, for three different ways of working.

Client SDKs

Generated for TypeScript, Python, PHP and Go, tracking the spec so a new endpoint arrives in your language without waiting on a hand-written wrapper.

The CLI

Built on the API in the tradition of gh and stripe: authenticate, deploy sites, manage domains, DNS and mail, drive backups, run wp-cli, tail logs and fire bulk operations. Where power users and agencies actually live.

The Terraform provider

Manage sites, domains, DNS records, mailboxes and plans as infrastructure as code. terraform apply provisions hosting, and your environments become reproducible and reviewable instead of a sequence of clicks nobody wrote down.

Interactive reference

Generated docs you can read and call from the browser, describing exactly the endpoints the server implements — because both come from the same spec.

Webhooks that survive your endpoint being down

Behind the platform is a durable event spine: every state change writes an event to a transactional outbox in Postgres, atomically with the database change, and a relay publishes it to NATS JetStream. Events are typed and versioned — site.deployed, order.paid, invoice.overdue, backup.completed, abuse.flagged, trial.ending and the rest.

Subscribe to what you care about

Register an endpoint as a WebhookSubscription and choose the event types it receives. One stream feeds notifications, analytics, automations and your integration alike — you are consuming the same events we do.

Signed with HMAC

Every delivery is HMAC-signed so you can verify it came from us before you act on it.

Retried with backoff, and logged

Failed deliveries retry with backoff and each attempt is recorded as a WebhookDelivery. You can inspect and replay deliveries from the dashboard rather than emailing support asking what we sent.

At-least-once, so dedupe on the id

The pipeline is deliberately at-least-once rather than pretending to be exactly-once. A relay that dies mid-publish has its claim lease expire and its events republished. Dedupe on the envelope id and your consumer is correct by construction.

Getting code onto the site

An API is only half a developer story. The other half is shipping.

  • Connect GitHub, GitLab or Bitbucket over OAuth, with deploy keys held in the credential store — not in a config file.
  • Push triggers a build-and-deploy pipeline, with branch-to-environment mapping (main to production, staging to staging) and per-stack build steps for composer and npm.
  • Roll back to a previous release when a deploy goes wrong.
  • Staging clone and push-to-live, so a change is proven somewhere real before it reaches visitors.
  • Jailed SSH, SFTP and FTP per site under CageFS isolation, so each tenant sees only their own files.
  • wp-cli from the panel terminal and over SSH.
  • VS Code in the browser via code-server — a full editor with extensions, an integrated terminal and git, editing the site's files directly.
  • Per-site PHP version, editable PHP settings, per-site extensions, environment variables and real cron alongside WP-cron.

And the same API your AI agent can use

We expose the platform as a hosted MCP server: a thin protocol adapter over the engine API that reuses the identical action catalogue, RBAC and audit trail. Connect Claude Code, Cursor, ChatGPT, Claude Desktop or any MCP-capable client once, and every capability we add to the API becomes available to it automatically.

The agent gets three things: Tools (the same API endpoints, no parallel logic to drift), Resources (read-only site health, config, recent logs, metrics, uptime and KB articles, so it diagnoses with real data before acting) and Prompts (published workflow templates such as "diagnose this site" or "prepare a migration").

Safety is the same story as authentication: OAuth 2.1, tokens bound to your org and RBAC permissions with row-level security enforced, scoped and revocable per tool, sandbox separated from production. Destructive actions — delete, suspend, billing, large spend — require explicit confirmation or a human-approval policy. Rate limits and spend caps bound AI-triggered paid actions, and every MCP call is audit-logged with identity, tool, arguments and result.

We support the protocol rather than integrating each app one at a time, which means your choice of AI tooling can change without your hosting integration changing with it.

FAQ

Is the public API the same one the dashboard uses?

Yes — it is the same engine API, published and hardened. The dashboard, admin console, CLI, Terraform provider, MCP server and webhooks are all consumers of one surface, which is why the API does not lag behind the panel.

Can I test an integration without spending money or building real servers?

Yes. Sandbox keys are issued separately from production keys and run in test mode: no real billing and no real provisioning. Point your CI at sandbox credentials and exercise the full request and response cycle safely.

How do I stop a retry from creating two of something?

Send an Idempotency-Key on your POST. The replay record is written on commit rather than inline, so a retry can never replay a cached success for a row that did not actually commit, and a request that fails releases its lock immediately so your corrected retry is not held up. Webhook delivery is at-least-once by design — dedupe on the envelope id at your end.

Can I give one API key access to all my client organisations?

Not today. API keys are issued per organisation, so an integration spanning several client orgs holds a key for each. Permissions are also checked per organisation for user principals: holding sites.create in one org grants nothing in another. That is deliberate — it keeps a compromised key's blast radius limited to a single tenant.

What does the built-in Developer role actually allow?

The dev role covers organisation read, API key management, viewing and creating sites, restarting them, purging their cache, and viewing and replying to tickets. It deliberately excludes billing control. Note that deploy and push-to-live permissions are not part of it — if a team member needs those, assign a role that carries them rather than assuming Developer is the broadest technical role.

What happens to my webhooks if my endpoint goes down for an hour?

Deliveries retry with backoff and every attempt is recorded as a WebhookDelivery you can inspect. Upstream, events are written to a transactional outbox in the same database transaction as the change itself, so nothing is lost while a consumer is unavailable — a down consumer lags, it never breaks the producer, and you can replay deliveries from the dashboard once you are back.

What does it cost to start building against it?

Start on a card-free 7-day trial of Footprint-Free Hosting — no payment details, up to 5 sites. Paid Footprint-Free tiers begin at $6/mo for PBN 5. Every plan carries a 30-day money-back guarantee, free migrations and no vendor lock-in.

Read the spec, then build against it

Spec-first API, generated SDKs, a CLI, a Terraform provider, signed webhooks and an MCP server — on hosting that already runs 100,000+ PBN sites across every niche. Start on a card-free 7-day trial, no payment details.

Start free