Not Organic / Integration guides
Build on a shared account.
Connect identity, scoped permissions, and metered services without passing provider credentials to a client.
Before you connect
Not Organic is the shared account and hosted-service layer for Twyne, Keating, Interleave, and Stich. Integrations use scoped access tokens bound to a proof key. An ordinary OpenAI API key is not a Not Organic credential.
This documentation is public; it does not establish open production enrollment. Obtain the appropriate product integration approval, confirm the API deployment is healthy, and use a test account before sending user data or paid requests.
| Address | Purpose |
|---|---|
https://api.notorganic.info | Gateway base URL, without a trailing /v1 in SDK configuration. |
https://id.notorganic.info | Sign-in and authorization portal. |
GET /healthz | Gateway store readiness. It is not a check of every upstream model or payment provider. |
Choose your integration
Read a wallet from your server
The SDK lives at packages/sdk in this repository. With repository access, run bun install --frozen-lockfile and import @notorganic/sdk from a workspace package. Public package-registry availability is not assumed by this guide.
Your trusted backend must supply a fresh product assertion whose granted capabilities include wallet:read. The assertion signing key must be registered with the gateway; do not create a production signing key in a browser.
import {
ServerClient,
createDpopKeyPair,
createDpopProofFactory,
exchangeProductAssertion,
} from "@notorganic/sdk";
// Call on a trusted server with a fresh, authorized product assertion.
// Assertions are single-use and valid for no more than 60 seconds.
export async function readWallet(
assertion: string,
request: typeof fetch = globalThis.fetch,
) {
const baseURL = "https://api.notorganic.info";
const keyPair = await createDpopKeyPair();
const token = await exchangeProductAssertion(
baseURL,
{
assertion,
dpop_jwk: keyPair.publicJwk,
scope: "wallet:read",
},
{ fetch: request },
);
const client = new ServerClient({
baseURL,
accessToken: token.access_token,
dpopProof: createDpopProofFactory(keyPair),
fetch: request,
});
return client.wallet.retrieve();
}
Download the TypeScript example. Call readWallet(freshAssertion) from your backend. The example exchanges once and immediately reads the wallet; it does not implement a long-lived token cache.
The returned access token lasts 300 seconds. For subsequent exchanges, mint a new assertion. Never reuse a consumed assertion or place tokens, assertions, or private keys in logs.
Make a metered request
After obtaining a token with the appropriate inference scope, create a ServerClient with that token and the matching DPoP proof factory. Set a spending reservation and an idempotency key explicitly.
const response = await client.responses.create(
{ model: "balanced", input: "Explain photosynthesis.", store: false },
{
maxCostMicrousd: 100_000, // $0.10 reservation
idempotencyKey: crypto.randomUUID(),
},
);client here is authenticated with infer:balanced, rather than the wallet-only scope in the first example. Read how reservations and actual costs differ before exposing spending controls to users.