September 2026
Pathly as an API, and a Terraform provider
Describing your infrastructure in files while creating your monitoring by hand means keeping two truths that eventually diverge. It can now be written as code: a documented API, and a Terraform provider.
The published contract is the one that runs
The API serves its own OpenAPI contract, without authentication, at a public address. That document is not written alongside the code: it is generated from the table that declares the routes, the very same one that decides, on every call, which scope is required. A route missing from it does not start. The developer page reads that contract at render time, so a removed endpoint disappears from the documentation without anyone thinking about it. Hand-copied documentation always lies, the only question is since when.
Narrow scopes, and four refusals
A key carries scopes shaped as resource then action: read scenarios, write them, trigger a run, close an incident. Writing implies reading, because a tool always re-reads what it has just written. Triggering stays separate from reading, because a run consumes quota and is not a consultation.
Four actions stay out of a key’s reach, by decision and not by oversight. Issuing or revoking a key, because a key able to do that cancels every other key’s scopes. Inviting a member, because it is the same thing by a detour: the new account will issue whatever keys it wants. Changing plan or touching billing, because a continuous integration token must not commit spending. Exporting the organisation, because the export contains members, therefore personal data.
What never comes back on a read
An authentication password, a webhook’s address, the steps of a browser journey: those values are written and never come back. In their place the API returns a twelve-character fingerprint, which changes as soon as the value changes. That is enough for a tool to detect that a resource was modified elsewhere, and far too little to reconstruct what it holds. Terraform uses it exactly that way: a webhook destination edited by hand in the console shows up on the next plan, without the address ever being written into a state file.
What an automated tool expects from an API
- Cursor pagination, not page numbers: a resource created during the walk would shift the pages, and the client would read a row twice or skip one.
- A Retry-After header when the rate limit is hit: without it, an automated client retries blindly and stays stuck in its own loop.
- An idempotency key replayed for twenty-four hours: a pipeline restarted after a network drop does not create duplicates.
- An identifier belonging to another organisation answers 404, never 403: answering “forbidden” would confirm that it exists.
The provider
Four resources — a scenario, a maintenance window, a webhook, an availability target — and a data source that re-reads the inventory, enough to spot a scenario created by hand in the console and missing from the code. API keys and members are absent, for the reason already given: a Terraform file that invites an owner is privilege escalation by detour.
Two behaviours matter more than the list of resources. After an apply, a plan must be empty: otherwise the tool proposes a change on every pass and nobody reads its plans any more. And changing a scenario’s address, interval or latency threshold must update it in place, never destroy and recreate it — a recreated scenario loses its history and its incidents, that is, everything it was watched for. Those two points required, on the API side, that everything writable be readable back identically. It is the provider’s least visible work, and the one that decides whether it is usable.
Adopting an existing estate
Nobody rebuilds their monitoring from scratch to move to code. Each resource can be imported by its identifier: the scenario created last year in the console enters Terraform state untouched, and the next plan shows the gap between what it is and what the file describes. That is the only honest way to migrate, and it is also the one that allows going back.
Where it stands
The provider is published on Terraform’s public registry, with its documentation and examples: a version declared in a required_providers block is now enough to install it, with no local mirror and no building from source. The numbering stays in 0.x, and that means something precise: existing resources will not move without reason, but we reserve the right to adjust a schema before 1.0. The API does not wait for the provider: a key, an address and the developer documentation are enough to drive the same things from any language.