Why no published SDK
Every "official" SDK is a versioning trap. Customers end up pinned to @dirtfleet/sdk@1.2.3 while the API ships flag.severity = AUTO_PM, and either we ship a breaking-change SDK release (annoying everyone) or we don't ship the feature (worse). OpenAPI + a generator lets the integrator pick their own re-gen cadence. The spec at /openapi.yaml is the source of truth; we add operations and component schemas without breaking the existing surface.
Bring our spec, pick your generator, get types.
TypeScript / Node
openapi-typescript (types) or openapi-fetch (full client)
Two tiers. openapi-typescript generates types only — pair with native fetch for the smallest dep footprint. openapi-fetch adds a tiny (~2kb) runtime that produces a typed get("/api/v1/assets") method shape.
# Types only — zero runtime
npx openapi-typescript https://dirtfleet.app/openapi.yaml \
-o ./src/dirtfleet.d.ts
# Then in your code
import type { paths, components } from "./dirtfleet";
type Asset = components["schemas"]["Asset"];
const res = await fetch(
"https://dirtfleet.app/api/v1/assets?limit=100",
{ headers: { Authorization: `Bearer ${KEY}` } },
);
const body = (await res.json()) as
paths["/api/v1/assets"]["get"]["responses"]["200"]["content"]["application/json"];
// body.assets is now typed Asset[]
# Or full client with tiny runtime
npm i openapi-fetch
npx openapi-typescript https://dirtfleet.app/openapi.yaml \
-o ./src/dirtfleet.d.ts
# Then
import createClient from "openapi-fetch";
import type { paths } from "./dirtfleet";
const client = createClient<paths>({
baseUrl: "https://dirtfleet.app",
headers: { Authorization: `Bearer ${KEY}` },
});
const { data, error } = await client.GET("/api/v1/assets", {
params: { query: { limit: 100 } },
});
// data.assets is typed; data is undefined when error is set
Go
oapi-codegen — types + client + servers
# Install
go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest
# Generate types + an http.Client-based client
oapi-codegen -package dirtfleet \
-generate types,client \
https://dirtfleet.app/openapi.yaml > dirtfleet/dirtfleet.go
# Use it
package main
import (
"context"
"fmt"
"net/http"
"dirtfleet"
)
func main() {
base := "https://dirtfleet.app"
c, _ := dirtfleet.NewClientWithResponses(base, dirtfleet.WithRequestEditorFn(
func(_ context.Context, req *http.Request) error {
req.Header.Set("Authorization", "Bearer dfk_...")
return nil
},
))
limit := 100
res, _ := c.ListAssetsWithResponse(context.Background(), &dirtfleet.ListAssetsParams{
Limit: &limit,
})
for _, a := range *res.JSON200.Assets {
fmt.Println(a.Id, a.Nickname)
}
}Python
datamodel-code-generator (Pydantic v2 models)
For a typed Python client, the simplest path is datamodel-code-generator emitting Pydantic v2 models, then any HTTP client (httpx, requests) parsing into them. The fullopenapi-python-client is also good if you want a generated client object.
# Install
pip install datamodel-code-generator httpx
# Generate the model file
datamodel-codegen \
--url https://dirtfleet.app/openapi.yaml \
--output dirtfleet_models.py \
--output-model-type pydantic_v2.BaseModel
# Use it
import os, httpx
from dirtfleet_models import Asset
KEY = os.environ["DIRTFLEET_API_KEY"]
r = httpx.get(
"https://dirtfleet.app/api/v1/assets",
params={"limit": 100},
headers={"Authorization": f"Bearer {KEY}"},
timeout=30,
)
r.raise_for_status()
assets = [Asset.model_validate(a) for a in r.json()["assets"]]
for a in assets:
print(a.id, a.nickname, a.meterType)Ruby
openapi-generator-cli (generates a typed module)
# Install the CLI (Java runtime required)
brew install openapi-generator # macOS
# or via npm:
npx @openapitools/openapi-generator-cli version
# Generate the ruby client
openapi-generator generate \
-i https://dirtfleet.app/openapi.yaml \
-g ruby \
-o ./dirtfleet_ruby
# Then
require "dirtfleet"
DirtFleet.configure do |c|
c.access_token = ENV["DIRTFLEET_API_KEY"]
end
client = DirtFleet::AssetsApi.new
resp = client.list_assets(limit: 100)
resp.assets.each { |a| puts "#{a.id} #{a.nickname}" }Other languages
Long tail
Anything with an OpenAPI 3.1 generator can read /openapi.yaml. Notable ones:
- Rust:
progenitor— generates an async reqwest-based client. - C# / .NET:
NSwagorkiota. - Java / Kotlin:
openapi-generator-cli -g javaor-g kotlin. - Swift: Apple's official
swift-openapi-generatorplugin. - PHP:
jane-php/open-apioropenapi-generator -g php.
Re-gen workflow
When to regenerate
The spec is additive between major versions: new endpoints, new optional fields, new enum members ship without breaking existing clients. Re-generate when you want to use new endpoints — your existing code keeps working untouched.
We bump to /api/v2/... only on breaking changes, and v1 stays available for at least 6 months after a v2 release. The OpenAPI spec carries both major versions during the deprecation window, so a re-gen during the overlap is safe — your client picks up v2 types alongside the v1 it currently uses.
← Back to the API reference · → Copy-paste examples · → OpenAPI page