TypeScript SDK
The memax-sdk client library. Typed access to the Memax REST API for Node, edge, and browser runtimes.
memax-sdk is the canonical TypeScript client for the Memax REST
API. It works in Node, edge runtimes (Cloudflare Workers, Vercel
Edge), and browsers — anywhere fetch is available.
Installation
npm install memax-sdkpnpm add memax-sdkyarn add memax-sdkbun add memax-sdkQuick start
import { Memax } from "memax-sdk";
const memax = new Memax({
apiKey: process.env.MEMAX_API_KEY!,
});
// Recall
const result = await memax.recall("how does auth work?");
for (const memory of result.memories) {
console.log(memory.title, memory.relevance_score);
}
// Push (convenience top-level — equivalent to memax.memories.push)
await memax.push("We chose Postgres for strong consistency", {
title: "Database decision",
tags: ["decisions", "infrastructure"],
hubId: "hub_abc123",
hubReason: "team decision, needs visibility",
});The exported class is Memax, not MemaxClient. The push
method takes (content, options) — there is no category or
boundary option (server classification is automatic; boundary is
derived from the target hub).
Configuration
const memax = new Memax({
apiKey: "mxk_...", // static key auth
// auth: async () => ({ Authorization: "Bearer …" }), // dynamic auth
apiUrl: "https://api.memax.app", // default
maxRetries: 2, // retries on transient errors
fetch: customFetch, // custom fetch (Node, tests, edge)
onWarning: (w) => console.warn(w), // API-returned warnings
});Pass one of apiKey or auth. apiKey is the static-key
path; auth is an async function returning headers — use it for
OAuth flows where the token rotates.
Top-level methods
The Memax class exposes three convenience shortcuts:
| Method | Equivalent to |
|---|---|
push() | memax.memories.push() |
recall() | memax.memories.recall() |
ask() | memax.memories.ask() |
Everything else is on resource sub-objects (memax.memories,
memax.hubs, memax.topics, memax.configs, …).
memax.recall(query, options?)
const result = await memax.recall("deployment process", {
limit: 5,
topicId: "top_xyz",
kind: "procedural",
hubId: "hub_abc123", // hub ID — boosts ranking for this hub
projectContext: { repo: "github.com/org/app" },
noRerank: false,
});hubId is sent as the X-Hub-ID request header — it must be a
hub ID (hub_…), not a slug. If you only know the slug,
resolve it to an ID first via memax.hubs.list() and match on
hub.slug (SDK memax.hubs.get(id) expects a hub ID). No hint
or threshold options. See
retrieval concepts for available knobs.
The tags option is declared on the recall request type but the
server currently ignores it on recall — treat it as a no-op for
now. Use kind, topicId, or hubId for filtering.
memax.push(content, options?)
const memory = await memax.push("Meeting notes from sprint planning…", {
title: "Sprint 42 planning",
tags: ["sprint", "planning"],
hint: "ephemeral context, safe to let cool quickly",
hubId: "hub_abc123", // hub ID, not a slug
hubReason: "team visibility into sprint decisions",
sourceAgent: "claude-code",
initiationType: "human_requested_agent",
projectContext: { repo: "github.com/org/app", branch: "main" },
});
// returns MemoryOther resources
// Memories
await memax.memories.list({ limit: 50, sort: "newest", hubId: "hub_abc" });
await memax.memories.get("mem_a1b2c3d4");
await memax.memories.update("mem_a1b2c3d4", { title: "New title" });
await memax.memories.delete("mem_a1b2c3d4");
await memax.memories.batchMove(["mem_a"], {
hubId: "hub_b",
topicId: "top_x",
});
// Hubs
await memax.hubs.list();
await memax.hubs.get("hub_abc");
await memax.hubs.createInvite("hub_abc", { role: "contributor" });
// Topics
await memax.topics.list("hub_abc");
await memax.topics.create({ name: "Auth & identity" }, "hub_abc");
await memax.topics.assignMemory("top_xyz", "mem_abc");
// Ask (LLM-synthesized answer grounded in your memories)
const answer = await memax.ask("How do we deploy to production?", {
model: "auto",
limit: 10,
});See the SDK source in
MemaxLabs/memax
for every resource's full method list and option types.
Error handling
import { Memax, MemaxError } from "memax-sdk";
try {
await memax.recall("query");
} catch (err) {
if (err instanceof MemaxError) {
console.error(err.code, err.status, err.message);
// Typed status-class helpers
if (err.isRateLimited) {
console.log(`Retry after ${err.retryAfterSeconds}s`);
}
if (err.isForbidden) console.log("Permission denied");
if (err.isNetwork) console.log("Offline / connectivity");
}
}MemaxError exposes code, status, retryAfterSeconds, and
boolean predicates: isRateLimited, isQuotaExceeded,
isForbidden, isNotFound, isConflict, isBadRequest,
isServerError, isNetwork, isUnauthorized. Prefer the
predicates over matching status numbers directly.
The SDK's maxRetries only retries the application-level not_ready error
code (used for async operations that weren't ready yet), with a fixed
retryDelayMs between attempts. It does not auto-retry HTTP 429s on
Retry-After. The Retry-After header is parsed and surfaced on the thrown
MemaxError (err.retryAfterSeconds) so your code can decide when to retry
rate-limited calls.