Build your first integration.
We'll wire up Margin, the reading companion from the overview, so that after a user connects it, Margin can (1) greet them with a recommendation that already knows their taste, and (2) remember a highlight they save. About ten minutes, server-side, in any stack — Node shown here.
1. Install the SDK
The SDK is a thin, typed wrapper over the REST API. One install:
pnpm add @pambase/sdk
2. Decide what Margin needs to do — its scopes
A scope is a single permission the user grants, like “read my reading notes.” You declare the full set your app may request when you register it; the user approves them on a consent screen. Margin reads and writes reading notes, learns preferences, reads context when a session starts, and hosts a chat — so its scopes are:
["identity:read", // the user's display name + tone preference"memory:read:note.*", // read reading notes/highlights it has saved"memory:write:note.*", // save new highlights as memories"memory:read:preference", // read tastes ("likes long-form essays")"memory:write:preference", // record tastes it observes"context:read:app.session.start", // pull relevant memory when a session opens"ai:host:chat" // run a memory-grounded chat]
The .* is a wildcard: memory:write:note.* covers note.reading, note.work, and any other note.<x>. Full grammar in Permissions.
3. Send the user to PAMbase to approve
From your app, redirect the user to the PAMbase Hub. They see exactly what Margin is asking for and approve. The state value is a random string you keep on the session and re-check on return — it protects against cross-site request forgery.
import { buildConnectUrl } from "@pambase/sdk";const url = buildConnectUrl({hubBaseUrl: "https://pambase.io", // http://localhost:3000 in devappSlug: "margin",redirectUri: "https://margin.app/connect/callback",state: crypto.randomUUID(), // save on the session; verify in step 4});res.redirect(url); // user lands on the consent screen, approves, comes back
4. Exchange the code for a connection token
After approval the user returns to your redirectUri with a one-time code. You trade that code (plus your client id/secret, server-side only) for a connection token — a long-lived credential that authorizes your calls for this user. Store it against your user record.
import { exchangeCodeForToken } from "@pambase/sdk";// 1. Verify state matches what you saved in step 3, then:const { connection_token, scopes } = await exchangeCodeForToken({apiBaseUrl: process.env.PAMBASE_API_URL!, // https://api.pambase.iocode: req.query.code,clientId: process.env.PAMBASE_CLIENT_ID!,clientSecret: process.env.PAMBASE_CLIENT_SECRET!,});await db.users.update(currentUser.id, { pambaseToken: connection_token });
client_secret. More in Security.5. Read: greet the user with a recommendation that knows them
Now create a client with that token and pull a brief — a short, plain-language summary of the user built from their memory. Drop it into your own model and your first recommendation already reflects their taste.
import { PAMbaseApp } from "@pambase/sdk";const pambase = new PAMbaseApp({baseUrl: process.env.PAMBASE_API_URL!,connectionToken: user.pambaseToken,});const system = await pambase.systemPrompt();// → "Reads widely on systems design and product; prefers long-form essays…"const reply = await yourLLM.chat({system, // <- the brief grounds your modelmessages: [{ role: "user", content: "What should I read this weekend?" }],});
No model of your own? Use PAMbase's hosted chat instead — it's already grounded in the user's memory: await pambase.chat({ intent: "app.companion.turn", userMessage: "What should I read?" }). See Host the agent.
6. Write: remember a highlight the user saves
When the user saves a highlight, remember it — plain text plus a kind and a scope. It's a durable memory now, and because it lives in the user's agent, every app they've allowed can recall it later.
const res = await pambase.remember({content: "Backpressure is how a system says 'slow down' instead of falling over.",kind: "event",scope: "note.reading",});// res.memoryIds → ["mem_…"] a memory now exists in note.reading
What you just did
- Connected Margin to the user's agent with their consent (steps 3–4).
- Read the user as a brief and grounded a recommendation in it (step 5).
- Remembered a highlight that became a durable, cross-app memory (step 6).
That's the whole loop. Everything else is depth on these moves.
Next
- Remember & recall — the full read/write loop.
- Signals & reacting — notify and react across apps.
- Choose your integration — recipes for your kind of app.