Skip to content

SDKs

SDKs

Zero-dependency clients for JavaScript and Python. One call asks the gate, waits for a person if it must, runs your code only on allow, and settles the outcome.

Everything the SDKs do is plain HTTP, documented in the API reference, so any language can call Immiscible directly. The SDKs exist to make the safe path the short one: guard() wraps the whole lifecycle so an agent cannot forget to wait or to settle.

JavaScript and TypeScriptPython
Package@immiscible/sdk, source in packages/immiscible-jsimmiscible, source in packages/immiscible-py
RuntimeNode 18 and later, Deno, Bun, browsers and edge runtimes; ESM and CommonJSPython 3.9 and later, standard library only
Dependenciesnonenone, including the Ed25519 receipt verifier
Typesbundled .d.tstype hints

#The lifecycle in one call

import { Immiscible, ImmiscibleDeniedError } from '@immiscible/sdk';

const gate = new Immiscible(); // reads IMMISCIBLE_AGENT_KEY and IMMISCIBLE_URL

try {
  await gate.pay(
    { amount: 4200, currency: 'GBP', merchant: 'grocer.example', provenance: [{ source: 'user' }] },
    (decision) => checkout(cart, decision.receipt), // runs only on allow
  );
} catch (err) {
  if (err instanceof ImmiscibleDeniedError) console.log(err.reasons, err.signals);
  else throw err;
}

That one call:

  1. asks the gate whether this agent may pay (with an idempotency key, so a retry never authorises twice);
  2. if a person must decide, waits, polling politely, and gives up with the approval link if nobody answers in time;
  3. runs your code only on allow;
  4. settles the action completed, or failed if your code threw.

If Immiscible cannot be reached, the call fails and your code never runs.

#Where it connects, and what it throws

Both SDKs talk to the hosted service, https://immiscible.fly.dev, unless you set IMMISCIBLE_URL (or pass baseUrl / base_url) to your own server; the CLI uses the same default.

HTTP failures arrive as a class you can catch by name, each still an ImmiscibleError carrying the server’s x-request-id:

ClassWhenCarries
ImmiscibleAuthenticationError401: the key is missing, unknown or revoked
ImmiscibleInvalidRequestError400 or 422errors, one entry per field
ImmiscibleRateLimitError429retryAfter (retry_after), in seconds
ImmiscibleIdempotencyConflictError409: the same idempotency key with a different body
ImmiscibleConnectionErrorthe server could not be reached or did not answer in time

#Verifying receipts

Both SDKs include an offline receipt verifier that checks the Ed25519 signature against a JWKS you fetched and kept, with no network call. It is how a merchant or a downstream service checks that an action was allowed. See verifying offline for what it checks.

#Without a server

Every example in the JavaScript package runs against a built-in fake, so you can write and test an integration before connecting anything:

Shell
cd packages/immiscible-js
node examples/shopping-agent.mjs --demo
node examples/merchant-checkout.mjs --demo

The Claude Code hook is its own package, @immiscible/claude-code-hook, in packages/immiscible-claude-code.