Discover the vocabulary.
The PAMbase contract — the scope taxonomy (the domains you write into) and the consent scopes — is discoverable at runtime, so you never hard-code assumptions. Two views answer two questions.
The two views
| Question | Call | Auth |
|---|---|---|
| What vocabulary exists? | getCatalog() | Public |
| What does this user have? | listUserScopes() | Token |
1. The catalog — what exists
Public, no auth. The memory kinds, the full scope taxonomy (grouped), intents, and webhook shapes — the same data rendered on the Catalog page.
| Endpoint | SDK | Returns |
|---|---|---|
GET /v1/catalog | getCatalog() | memoryKinds, scopeGroups, standardScopes, standardIntents, webhookEvents + version |
const catalog = await pambase.getCatalog();// catalog.version, catalog.standardScopes, catalog.scopeGroups, catalog.memoryKinds// Public — also reachable without a token:// GET http://localhost:4000/v1/catalog
2. This user's scopes — what you can actually use
listUserScopes() returns the scopes this connection holds (filtered to what your app may read), each with a memory count and a standard flag. Adapt your UI to what's really there — don't offer a feature for data the user doesn't have.
| Endpoint | SDK | Returns |
|---|---|---|
GET /v1/scopes | listUserScopes() | { scopes: [{ scope, count, standard }] } |
const { scopes } = await pambase.listUserScopes();const has = (ns: string) => scopes.some(s => s.scope.startsWith(ns) && s.count > 0);// Margin only shows the "Your highlights" shelf if the user actually has note.* memories.if (has("note")) showHighlightsShelf();else showEmptyState("Save your first highlight to start your shelf.");// And only surfaces taste-based picks if it can read preferences with data behind them.const canPersonalize = has("preference");
memory:read:note.* but have an empty store, or grant fewer scopes than your manifest requested. Check counts here before rendering a feature. This is also the first thing to check when a recall() comes back empty — see Troubleshooting.Types for autocomplete
The SDK ships STANDARD_SCOPE_NAMESPACES (and the MemoryScope type) so your editor autocompletes the standard domains when you remember(). Sub-scopes under a standard namespace are free.
import { STANDARD_SCOPE_NAMESPACES } from "@pambase/sdk";await pambase.remember({ content: "Trains for trail runs.", kind: "goal", scope: "fitness.trail" });// "fitness" is a standard namespace; ".trail" is your free sub-scope.
What to expect next
- Catalog — the rendered scope taxonomy.
- Manifest — declaring the scopes your app requests.
- Remember & recall — write into the scopes you discovered.