memorysync-sdk
v1.9.1
Published
Official JavaScript / TypeScript client for the MemorySync API.
Maintainers
Readme
memorysync-sdk
Official JavaScript / TypeScript client for the MemorySync API.
npm install memorysync-sdkQuick start
import { MemorySyncClient } from "memorysync-sdk";
const ms = new MemorySyncClient({
apiKey: process.env.MEMORYSYNC_API_KEY!,
baseUrl: "https://api.memorysync.io",
// optional:
projectId: "proj_xxxxxxxxxxxxxxxx",
endUserId: "user_42",
});
await ms.add({ text: "User prefers dark mode." });
const { memories } = await ms.query({ query: "ui preferences", k: 5 });
for (const m of memories) console.log(m.id, m.text);Configuration
| Field | Required | Description |
| ------------ | -------- | -------------------------------------------------------------------------------------------- |
| apiKey | yes | Sent as X-API-Key. Provision in your MemorySync dashboard. |
| baseUrl | yes | The deployment URL of your MemorySync instance. |
| projectId | no | Pin the client to a single project (X-Project-ID). Format: proj_ + 16 hex chars. |
| endUserId | no | Identify which of your users this client speaks for (X-End-User-ID). |
| timeoutMs | no | Per-request timeout. Default 30000. |
| fetch | no | Inject a custom fetch (tests, Node 16). Defaults to global fetch (Node 18+, all browsers). |
endUserId can also be passed per-call on add() to override the client default.
Methods
Every method is a thin wrapper over a real HTTP route. There are no hidden side effects.
| Method | Route |
| ------------------------------------- | -------------------------------------- |
| add(req) | POST /memory/add |
| bulkAdd(items, { deduplicate? }) | POST /memory/bulk-add |
| query(req) | POST /memory/query |
| get(memoryId) | GET /memory/{id} |
| update(memoryId, req) | PATCH /memory/{id} |
| forget(memoryIds, reason?) | DELETE /memory/forget |
| summarize(req) | POST /memory/summarize |
| compose(req) | POST /memory/compose |
| exportAll() | GET /memory/export |
| createRelation(fromId, req) | POST /memory/{id}/relations |
add returns one of two shapes
add() is routed through MemorySync's extraction pipeline. Inputs that carry no
high-value content are intentionally skipped. The discriminator is the status
field on the skipped envelope:
const result = await ms.add({ text: "User prefers dark mode." });
if ("status" in result && result.status === "skipped") {
// result.reason, result.candidatesExtracted, result.candidatesStored
} else {
// result is a MemoryRecord — result.id, result.text, result.createdAt, ...
}Control-plane client
ControlPlaneClient is a separate bearer-authenticated client for trusted dashboard and administrative flows. It never sends an API key, persists login tokens, or refreshes tokens automatically. login() is the only method that does not require accessToken.
import { ControlPlaneClient } from "memorysync-sdk";
const control = new ControlPlaneClient({
baseUrl: "https://api.memorysync.io",
accessToken: process.env.MEMORYSYNC_ACCESS_TOKEN,
projectId: "project_abc123", // optional X-Project-ID default
});
const plan = await control.getCurrentPlan();
const hooks = await control.listWebhooks({ projectId: "project_override" });
// This returns tokens but does not store them on the client.
const login = await new ControlPlaneClient({
baseUrl: "https://api.memorysync.io",
}).login({ email: "[email protected]", password: "..." });Control-plane configuration accepts baseUrl, optional accessToken, optional projectId, optional timeoutMs, and optional injectable fetch. Every call accepts a final { projectId? } override. Public request and response fields are camelCase; the client explicitly encodes documented snake_case wire fields and normalizes response objects.
| Method | Route |
| --- | --- |
| bulkRevokeApiKeys(req, options?) | POST /org/api-keys/bulk-revoke |
| testApiKey(keyId, options?) | POST /org/api-keys/{key_id}/test |
| login(req, options?) | POST /auth/login |
| getCurrentPlan(options?) | GET /org/billing/current-plan |
| listTeamMembers(options?) | GET /admin/team/members |
| suspendTeamMember(memberId, options?) | PATCH /admin/team/members/{member_id} |
| removeTeamMember(memberId, options?) | DELETE /admin/team/members/{member_id} |
| listSessions(options?) | GET /auth/sessions |
| revokeSession(sessionId, options?) | POST /auth/sessions/{session_id}/revoke |
| listAuditEvents(query?, options?) | GET /admin/audit-logs |
| listIntegrations(query?, options?) | GET /api/v1/integrations/catalog |
| createOrganization(req, options?) | POST /organizations |
| listOrganizations(options?) | GET /organizations |
| listOrganizationMembers(options?) | delegates to listTeamMembers |
| getOrganizationSettings(query?, options?) | GET /admin/tenant-settings |
| listProjects(options?) | GET /org/projects |
| createWebhook(req, options?) | POST /org/webhooks |
| listWebhooks(options?) | GET /org/webhooks |
| updateWebhook(endpointId, req, options?) | PATCH /org/webhooks/{endpoint_id} |
| deleteWebhook(endpointId, options?) | DELETE /org/webhooks/{endpoint_id} |
| testWebhook(endpointId, req?, options?) | POST /org/webhooks/{endpoint_id}/test |
| replayWebhookDeliveries(endpointId, req?, options?) | POST /org/webhooks/{endpoint_id}/replay |
| listWebhookDeliveries(endpointId, query?, options?) | GET /org/webhooks/{endpoint_id}/deliveries |
Errors
Every non-2xx response throws a typed subclass of MemorySyncError:
| Class | When |
| ----------------- | ------------------------------------------- |
| AuthError | 401 / 403 — bad key, missing scope. |
| ValidationError | 400 / 409 / 422. |
| NotFoundError | 404 — record not visible to the caller. |
| RateLimitError | 429 — read err.retryAfterSeconds. |
| ServerError | 5xx. |
| MemorySyncError | Network errors, timeouts, anything else. |
Every error carries statusCode, response, and the server-issued requestId
(when present) for support escalation.
import { RateLimitError } from "memorysync-sdk";
try {
await ms.add({ text });
} catch (err) {
if (err instanceof RateLimitError) {
await new Promise((r) => setTimeout(r, err.retryAfterSeconds * 1000));
} else {
throw err;
}
}License
MIT
