TypeScript SDK
A typed, fetch-based TypeScript client for the Minctrl API — run the governed start → park → resume loop from Node or the browser.
The TypeScript SDK (@minctrl/sdk) is a thin, typed client over the global
fetch. Its surface mirrors the real API routes one-to-one — grouped as auth,
templates, connectors, and runs — and its request-body types are generated
from the OpenAPI schema, so anything you can do with the
API reference you can do in a few typed lines.
Install
npm install @minctrl/sdkRequires Node 20+ or any runtime with a global fetch. ESM and CommonJS builds
and full type declarations are shipped — no runtime dependencies.
Quickstart
Create a client, authenticate, and run the governed cycle: a run proceeds on its own until governance parks it on a gate, then you resume it with the gate step-id.
import { createMinctrl } from "@minctrl/sdk";
const mc = createMinctrl({ baseUrl: "https://app.minctrl.com" });
// Authenticate — attach the returned token to the client.
const { token } = await mc.auth.login({
email: "jane.doe@acme-health.com",
password: "<your-password>",
});
mc.setToken(token!);
// Start a run. inputs are the seed facts steps and connectors read from.
const run = await mc.runs.start({
vertical: "aml",
inputs: { member_id: "M-10293", customer_name: "Jane Q. Public" },
});
// The run parks when governance needs a human. Sign the gate STEP-ID
// (not the "gate:" display label) to continue.
if (run.status === "parked") {
await mc.runs.resume(run.run_id!, { gate: "bsa-gate", decision: "approved" });
}Gate = step-id
runs.resume(...) takes the gate step-id the run parked on — the id in the
parked run's state — not the gate:-prefixed display label. Passing the label
will not resolve the parked gate.
Irreversible tools stay shadowed
Even with auto_resolve: true (the default), a connector bound to an
irreversible tool-id runs in shadow — no real call is made — unless its
config sets reversible: true. The autopilot never fires a live irreversible
action on your behalf.
Client surface
Every group maps directly onto the API:
| Group | Methods | Routes |
|---|---|---|
mc.auth | register, login, me | /auth/register, /auth/login, /auth/me |
mc.templates | list, canvas, bpmn | /process-templates/, /process-templates/{vertical}/canvas, /process-templates/{vertical}/bpmn |
mc.connectors | list, upsert, test, delete | /connectors/, /connectors/{tool_id} (+ /test) |
mc.runs | start, get, resume, list | /process-runs/, /process-runs/{run_id} (+ /resume) |
The client always sends and expects JSON, sets Authorization: Bearer <token>
when a token is present, follows redirects, and throws a typed MinctrlError
(with .status and .body) on any non-2xx response.
Binding a connector
Bind a process tool-id to one of your own HTTP endpoints. Keep reversible: false
so an irreversible screen stays shadowed until you explicitly opt in.
await mc.connectors.upsert("sanctions-screen", {
base_url: "https://screening.vendor.com",
method: "POST",
path: "/v1/screen",
auth_type: "bearer",
auth_token: "<your-token>",
body_map: { full_name: "customer_name" },
signal_rule: { path: "match_score", op: "lt", value: 0.85, pass: "clear", fail: "hit" },
reversible: false,
});Authentication
Every method except auth.register and auth.login requires a bearer token. Set
it at construction or after logging in — the SDK sends it as
Authorization: Bearer <token> on each request:
// At construction:
const mc = createMinctrl({ baseUrl: "https://app.minctrl.com", token: "<token>" });
// Or after login/register:
const { token } = await mc.auth.login({ email: "jane.doe@acme-health.com", password: "<your-password>" });
mc.setToken(token!);See also
- API reference — every operation and model, generated from the OpenAPI schema.
- Run a governed process — the start → park → resume loop in depth.