OpenAPI code generation
The Elastio API is described by an OpenAPI 3.0.3 document at /openapi/elastio-api.json. Feed it to a code generator to get typed models and one method per operation in the language you use.
Generated clients are large (the spec has hundreds of operations) and are only as stable as the spec. Pin the spec version you generated from, commit the output or regenerate in CI, and review the diff when you update.
Get the spec
Section titled “Get the spec”curl -sSo elastio-api.json https://developer.elastio.com/openapi/elastio-api.jsonjq -r '.openapi, .info.version' elastio-api.jsonGenerate from a local copy rather than the live URL so your builds are reproducible.
openapi-generator
Section titled “openapi-generator”OpenAPI Generator supports dozens of languages. Run it with npm or Docker; both need Java or Docker available.
npm install --save-dev @openapitools/openapi-generator-clinpx openapi-generator-cli versiondocker run --rm -v "$PWD:/local" openapitools/openapi-generator-cli version# Use /local/elastio-api.json as the input and /local/<dir> as the output below.TypeScript (fetch)
Section titled “TypeScript (fetch)”npx openapi-generator-cli generate \ -i elastio-api.json \ -g typescript-fetch \ -o ./elastio-ts \ --additional-properties=supportsES6=true,npmName=elastio-api-clientOperations are grouped into one API class per tag (IncidentsApi, SlackApi, …). The Bearer scheme reads accessToken from the configuration:
import { Configuration, IncidentsApi } from './elastio-ts';
const config = new Configuration({ basePath: 'https://acme.app.elastio.com', accessToken: process.env.ELASTIO_TOKEN,});
const incidents = await new IncidentsApi(config).listIncidents({ status: 'open', limit: 20 });console.log(incidents.total, incidents.data.map((i) => i.handle));npx openapi-generator-cli generate \ -i elastio-api.json \ -g go \ -o ./elastio-go \ --additional-properties=packageName=elastio,isGoSubmodule=truenpx openapi-generator-cli generate \ -i elastio-api.json \ -g java \ -o ./elastio-java \ --additional-properties=library=native,groupId=com.example,artifactId=elastio-api-client,apiPackage=com.example.elastio.api,modelPackage=com.example.elastio.modelPython
Section titled “Python”npx openapi-generator-cli generate \ -i elastio-api.json \ -g python \ -o ./elastio-py \ --additional-properties=packageName=elastio_apipip install ./elastio-pyimport osimport elastio_api
config = elastio_api.Configuration( host="https://acme.app.elastio.com", access_token=os.environ["ELASTIO_TOKEN"],)with elastio_api.ApiClient(config) as client: page = elastio_api.IncidentsApi(client).list_incidents(status="open", limit=20) print(page.total)If you only need a handful of calls, the hand-written Python reference client is much smaller.
oapi-codegen for Go
Section titled “oapi-codegen for Go”oapi-codegen generates idiomatic Go types and a client from OpenAPI 3.0 documents.
go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latestCreate oapi-codegen.yaml:
package: elastiooutput: elastio/client.gen.gogenerate: models: true client: truemkdir -p elastiooapi-codegen -config oapi-codegen.yaml elastio-api.jsonAdd the token with a request editor:
package main
import ( "context" "fmt" "log" "net/http" "os"
"example.com/yourmodule/elastio")
func main() { auth := func(ctx context.Context, req *http.Request) error { req.Header.Set("Authorization", "Bearer "+os.Getenv("ELASTIO_TOKEN")) return nil }
c, err := elastio.NewClientWithResponses("https://acme.app.elastio.com", elastio.WithRequestEditorFn(auth)) if err != nil { log.Fatal(err) }
limit := 20 resp, err := c.ListIncidentsWithResponse(context.Background(), &elastio.ListIncidentsParams{Limit: &limit}) if err != nil { log.Fatal(err) } if resp.JSON200 == nil { log.Fatalf("unexpected status %d: %s", resp.StatusCode(), resp.Body) } fmt.Println(len(resp.JSON200.Data), "incidents on this page")}Caveats
Section titled “Caveats”- Names come from
operationId. Generators turn each operation’soperationIdinto a method name, solistIncidentsbecomeslistIncidents()in TypeScript,list_incidents()in Python andListIncidents…()in Go. The spec mixes camelCase (listIncidents) and snake_case (list_scan_job_threats) IDs; generators normalize both, but search the generated code by operation ID rather than guessing. - A few operations have no
operationId. The generator invents a name from the method and path for those (some Database Monitoring operations). Those names can change if the path changes. - Classes follow tags. Tag names contain spaces (
Scan Jobs,Personal Access Tokens), which becomeScanJobsApi,PersonalAccessTokensApiand so on. - Two security schemes.
authorizationis the personal access token used by almost every operation.bearerAuthis the separate integration token used by the Wiz operations. Generated clients expose both; set the one the operation needs. - The server URL has a variable. The spec’s server is
https://{tenant}.app.elastio.comwith the defaultyour-tenant. Always pass your own base URL. - Pagination isn’t generated. Generated methods return one page. Loop yourself using the operation’s pagination parameters; see Pagination.
- Errors. Non-2xx responses carry the gateway envelope
{ "status", "error", "message" }. Most generators raise a generic API exception with the raw body; parse it to showmessage. See Errors.