Integrating with an external API doesn’t have to mean hand-writing HTTP requests, guessing payload shapes, or chasing runtime errors. In this post, we’ll walk through how to get started with the Golioth Management API from a TypeScript-based Node.js backend using auto generated types from our OpenAPI definition.
By the end, you’ll have:
- A Node.js project written in TypeScript
- Fully typed API bindings generated from Golioth’s OpenAPI spec
- API authentication handled cleanly with a
.envfile - A small example that talks to the Golioth Management API
Why OpenAPI + TypeScript?
Golioth Management API is published as an OpenAPI definition. This means we can automatically generate:
- Strongly typed request and response objects
- Autocomplete in your editor
- Compile-time errors instead of runtime surprises
For backend developers, this removes a lot of guesswork and makes refactoring much safer.
1. Create a new Node.js + TypeScript project
Before we start, you’ll need:
- Node.js 18+ installed
- Basic familiarity with TypeScript
- A Golioth account and an API key
Start by creating a new project directory and initializing it:
mkdir golioth-demo
cd golioth-demo
npm init -y
Install the basic dependencies:
npm install dotenv
npm install --save-dev typescript tsx @types/node
Initialize TypeScript:
npx tsc --init
We now have a minimal TypeScript-enabled Node.js project, let’s start integrating!
2. Store your API key context using a .env file
The Golioth API requires an API key to be passed in a header. You should never hardcode a secret key into your code, as it can easily fall into the wrong hands. Instead, you can set up your application to pull the secret from the execution environment, which allows you to keep your API keys stored in your deployment environment, and use different credentials in different environments.
API keys can only be used to access APIs for the project they’re attached to. To keep things portable, we’ll put the project and organization IDs in the environment as well, allowing our application to work with any project without having to change the code.
A common solution for managing growing execution environments is to add a .env file in the project root:
GOLIOTH_API_KEY=your-api-key
GOLIOTH_ORG=your-org-id
GOLIOTH_PROJECT=your-project-id
Then load it in your application’s src/index.ts using dotenv:
import 'dotenv/config';
Now your API key is available at runtime as:
process.env.GOLIOTH_API_KEY
3. Generate TypeScript bindings from the OpenAPI spec
To generate the TypeScript bindings for the Golioth API, we’ll use the Swagger TypeScript API package. This provides a flexible set of configuration parameters that allows us to fine tune the generated TypeScript code to make the Golioth API integration as simple as possible.
First, we’ll need to install the generator:
npm install --save-dev swagger-typescript-api
Although swagger-typescript-api can be run as a command line tool with npx, it’s easier to set up its configuration by wrapping it up in a little script that runs the code generation. It’ll also allow us to tweak the generated code a bit.
Create a scripts directory at the root of your repository, and add the following to a TypeScript file named golioth.ts:
import path from "node:path";
import { generateApi } from "swagger-typescript-api";
const fromEnv = {
projectId: "GOLIOTH_PROJECT",
organizationId: "GOLIOTH_ORG",
};
type PName = keyof typeof fromEnv;
generateApi({
url: "<https://api.golioth.io/openapi.json>",
apiClassName: "Golioth",
output: path.resolve("src/api"),
fileName: "golioth.ts",
// split API into modules:
moduleNameFirstTag: true,
// Unwrap the json data in the response:
unwrapResponseData: true,
// Skip predefined parameters:
hooks: {
onCreateRoute(routeData) {
routeData.request.parameters =
routeData.request.parameters?.filter(
(p) => !fromEnv[(p as { name: PName }).name]
) ?? [];
return routeData;
},
onInsertPathParam(paramName) {
if (paramName in fromEnv) {
return `process.env.${fromEnv[paramName as PName]}`;
}
},
},
});
The configuration is fairly straight forward, but the hooks are an important addition here: The keys in the fromEnv object will be replaced with their mapped environment variables. We’ll get to why that’s important in a little bit!
Finally, add this as a script in your package.json:
// ...
"scripts": {
// ...
"generate:golioth": "tsx scripts/golioth.ts"
}
}
And run the script to generate the TypeScript bindings:
npm run generate:golioth
After this completes, a new golioth.ts file gets added to src/api, containing several thousand lines of type definitions, including a Golioth class, which we’ll use to instantiate our API.
4. Create and configure the Golioth API client
With the generated bindings and API key in place, creating a client is straightforward.
We find it’s cleanest to instantiate the Golioth client in a separate file, and export it as a const. Create a new file called src/golioth.ts:
import { Golioth } from "./api/golioth";
export const golioth = new Golioth({
baseApiParams: {
headers: {
// Pulling the API key from the execution environment:
"X-Api-Key": process.env.GOLIOTH_API_KEY,
},
},
});
At this point, you already have:
- Authentication wired up
- A fully typed API client
- Editor autocomplete for all endpoints
5. Make your first API call
Let’s make a simple request to verify everything works.
For example, fetch a list of devices in your project:
import 'dotenv/config';
import { golioth } from "./golioth"
async function listDevices() {
const devices = await golioth.devices.devicesList();
devices.list?.forEach(device => {
console.log(`- ${device.id}: ${device.name}`);
})
}
listDevices().catch(console.error);
Notice a few things:
- The method names come directly from the OpenAPI spec
- Response objects are fully typed
- TypeScript helps you discover fields without checking the docs
This is also where the hooks in the configuration come in to make life a little easier for us! All Golioth APIs are prefixed with a project ID (and occasionally, an organization ID), and the hooks we added let us skip these parameters in the function call.
Summary
In just a few steps, we:
- Created a TypeScript Node.js project
- Generated strongly typed API bindings from Golioth’s OpenAPI definition
- Secured our API key using environment variables
- Made our first request to the Golioth Management API
If you’re building a backend service and want a type-safe, low-friction way to integrate with Golioth, we think this is the fastest way to get started.
Happy building!


No comments yet! Start the discussion at forum.golioth.io