Developer tools

Developer tools

SDKs

The client libraries for Rust, TypeScript, Python, Go, C# and Java, how to add each, and what they do the same in every language.

Six libraries, at 0.2.2 (Go at 0.2.3, which changed only its README), all open source in inorbithr/sdk. Each is a hand-written runtime (the client, credentials, retries, errors, streams) plus the API's operations as typed calls. Four are on their language's registry; C# and Java are built and tested at 0.2.2 but not published yet.

LanguagePackageNeedsWhere
RustinorbithrRust 1.94crates.io
TypeScript@inorbithr/sdkNode 22.12, Bun, Deno, browsersnpm, JSR
PythoninorbithrPython 3.11PyPI
Gogithub.com/inorbithr/sdk/goGo 1.26pkg.go.dev
C#InOrbit.Sdk.NET 8build from source; not on NuGet yet
Javahr.inorbit:inorbit-sdkJava 17build from source; not on Maven Central yet

Every library reads its credential from the environment: an API token in INORBIT_TOKEN (made in the console or with iohr token create), or an API key in INORBIT_KEY_ID and INORBIT_KEY_SECRET with the scopes to ask for in INORBIT_SCOPES, which it exchanges for 15-minute tokens and refreshes itself.

iohr sdk add (command line 0.1.0-alpha.10 and later) adds the library to the project in the current directory with the package manager the project already uses, so each section below shows it first and the package manager's own command beside it. Without a language it finds the project from the current directory up to the repository root (Cargo.toml, package.json or deno.json, pyproject.toml, requirements.txt or a Python lock file, go.mod); when it finds several or none it exits 2 and names the commands. It picks the manager from the project's files: pnpm, yarn, bun or npm by lock file or packageManager, deno add jsr: for deno.json without package.json; uv, poetry or pdm by lock file, otherwise pip only inside an active virtualenv, and it refuses (exit 2) to install into a system Python. cargo add needs a Cargo.toml and go get a go.mod.

iohr sdk add                         # the language and the package manager from the project's files
iohr sdk add go --version 0.2.2      # that release
iohr sdk add --dry-run               # print the command, run nothing
iohr sdk add ts --json               # {"lang", "manager", "dir", "command", "dry_run"}

It always prints the command first, then runs that one program directly in the project directory: no shell, never sudo, the program found only in absolute PATH entries. The exit code is the package manager's. iohr contacts no host for it; the package manager reaches its own registry. C# and Java are refused (exit 1): they are not on NuGet or Maven Central yet.

Rust

iohr sdk add rust     # or: cargo add inorbithr
use inorbithr::{Client, Error, Method, Operation, Response};

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Error> {
    let client: Client = Client::from_env()?;
    let me: Response<serde_json::Value> = client
        .request(Operation::new(Method::Get, "/v1/me"))
        .await?;
    println!("{} ({})", me.value["subject"], me.value["kind"]);
    Ok(())
}

TypeScript

iohr sdk add typescript     # or: npm install @inorbithr/sdk, pnpm add @inorbithr/sdk, deno add jsr:@inorbithr/sdk
import { Public } from "@inorbithr/sdk";

const api = Public.fromEnv();
const { value: me } = await api.me();
const { value: page } = await api.radar.listDigests({ limit: 3 });

ESM only, no dependencies; runs on Node, Bun, Deno, browsers and Workers. 64-bit integers are bigint.

Python

iohr sdk add python     # or: uv add inorbithr, pip install inorbithr in a virtualenv
from inorbithr import Public

api = Public.from_env()
me = api.me().value
digests = api.radar.list_digests(limit=3).value

AsyncPublic is the same on asyncio.

Go

iohr sdk add go     # or: go get github.com/inorbithr/sdk/go@latest
import (
	inorbit "github.com/inorbithr/sdk/go"
	"github.com/inorbithr/sdk/go/public"
)

api, err := public.FromEnv()
if err != nil {
	return err
}
me, err := api.Me(ctx)
var apiErr *inorbit.APIError
if errors.As(err, &apiErr) && apiErr.Code == inorbit.CodeForbidden {
	// the token lacks identity:read
}

inorbit is the runtime; public is the surface an API token or key may call. OpenTelemetry is a separate module, github.com/inorbithr/sdk/go/otel, so the runtime does not depend on it.

C#

InOrbit.Sdk 0.2.2 (net8.0) is built and tested in the open, and its NuGet release has not happened yet. Build from source until then, and reference the project:

git clone https://github.com/inorbithr/sdk
dotnet add reference path/to/sdk/csharp/src/InOrbit.Sdk
using InOrbit.Sdk;
using InOrbit.Sdk.Api;

using var client = Client.FromEnv();
var me = (await client.MeAsync()).Value;

Java

hr.inorbit:inorbit-sdk 0.2.2 is built and tested in the open, and its Maven Central release has not happened yet. Build from source until then: put it in your local Maven repository and depend on it by the coordinates it will be published under.

git clone https://github.com/inorbithr/sdk && cd sdk
mvn -f java install
<dependency>
  <groupId>hr.inorbit</groupId>
  <artifactId>inorbit-sdk</artifactId>
  <version>0.2.2</version>
</dependency>
Public api = Public.fromEnv();
Me me = api.me().value();

Configuration and middleware

From 0.2.2 every library has the same configuration and middleware:

  • load (Client::load, Client.load, inorbit.Load, Client.Load) reads settings in one order: code, then INORBIT_* environment variables, then the iohr config file, then defaults. describe() shows each value and where it came from, with secrets redacted; iohr sdk config prints the same for a program on your machine.
  • The credential chain: environment, token and key secret files, then your iohr login (iohr auth token).
  • Proxy, CA bundle, mTLS, key pinning and connect timeout, or your own HTTP client.
  • A named middleware pipeline with built-ins for logging, OpenTelemetry, rate limits and a retry budget.

Two changes a running program can notice: writes whose operation takes an Idempotency-Key are now retried, with one key per call sent on every attempt, and calls have a 120 s total deadline by default, every attempt and wait included. The settings are in docs/config.md, worked examples in docs/recipes.md.

A client cut to your credentials

Public (and its counterpart in each language) holds every operation an API credential may call. iohr sdk generate writes a surface into your repository with only the operations your profiles' credentials may call, so a call a profile may not make does not compile (in Python, pyright and mypy refuse it), and iohr sdk check fails in CI when that set moves:

iohr sdk generate --lang rust --for default --out src/iohr   # or typescript, python, go, csharp, java
iohr sdk check

The full guide is public: Generate an SDK for your account.

What every library does

  • Authenticates with an API token, or exchanges an API key for a short-lived token, caches it and refreshes it.
  • Returns typed results and one error type per language, carrying the API's error code and details; a code the library does not know yet is kept, not dropped.
  • Retries what is safe to retry (429, 503, 504, connection failures), honouring Retry-After; a write is retried only when the operation is marked safe to repeat.
  • Reads streams over server-sent events or one /v1/ws socket.
  • Behaves the same in every language: one set of conformance cases runs against all six.

Checking a package

RegistryHow
npmnpm audit signatures checks registry signatures and provenance
PyPIeach file carries a PEP 740 attestation; pypi-attestations verify pypi --repository https://github.com/inorbithr/sdk <file>
Gothe toolchain checks every module against sum.golang.org
JSRprovenance on the package page, linked to the transparency log
crates.ioCargo checks every download against the index's checksum

The details are in the SDK repository's verifying releases.