Skip to content

TypeScript client

npm install @sloose/api-client

Every path, parameter, body and response comes from the same document that generates the API reference, so the client cannot describe an endpoint the server does not have — and a route that changes shape breaks the build of code still using the old one.

import { createClient } from '@sloose/api-client';
const sloose = createClient({
token: process.env.SLOOSE_TOKEN!,
environment: 'production',
});
const { projects } = await sloose.get('/orgs/{org}/projects', {
params: { path: { org } },
});

get, post, put, patch and delete return the response body. Anything that is not a 2xx throws.

For local development, pass an origin instead of an environment:

const sloose = createClient({ baseUrl: 'http://localhost:8787', token });

Refusals use a closed set of codes, so catching and switching is the intended shape:

import { isApiError } from '@sloose/api-client';
try {
const run = await sloose.post('/entitlements/runs/authorise', {
body: { declaredRows: rows.length, projectId: null },
});
} catch (err) {
if (!isApiError(err)) throw err;
if (err.code === 'LIMIT_RUNS' || err.code === 'LIMIT_ROWS_PER_RUN') {
// err.body carries runsRemaining, or rowsPerRun
return offerUpgrade();
}
throw err;
}

SlooseApiError carries:

status the HTTP status
code the machine-readable reason, when there is one
body the whole parsed body — issues, balance, project, missing
response the raw Response, for headers
isReason whether this is a plan or status refusal rather than a bad request

A request that never reached the API throws SlooseNetworkError instead, so a dropped connection is never mistaken for a rejection.

import { REASON_CODES, isReasonCode, type ReasonCode } from '@sloose/api-client';

Exported as an array as well as a type, so you can switch exhaustively and have the compiler tell you when a new one appears.

sloose.raw is the underlying openapi-fetch client, if you would rather have { data, error } than exceptions, or want to add middleware:

const { data, error, response } = await sloose.raw.GET('/health');

Both a session token and an org API token work everywhere except the three session-only routes. See Authentication.