MemorySyncMemorySync
SDKs

Language-Agnostic Patterns

The following patterns hold no matter which client (or raw HTTP) you use. Header names, field names, status codes, and limits are the same across Python, Node, and direct cURL. Learn them once, apply them everywhere.

The headers every request carries

Both clients send the same headers. If you skip the SDKs and call the API directly, you must set these yourself.

HeaderRequiredWhat it does
X-API-KeyYesYour API key. Always sent, even by SDK methods that look read-only.
Content-TypeOn bodiesAlways application/json.
AcceptRecommendedapplication/json; the API never returns anything else.
X-Project-IDOptionalScopes the call to a specific project. Both clients accept it on the constructor.
X-End-User-IDRequired for API-key authIdentifies which of your end users the request belongs to. The server returns 400 MISSING_END_USER_ID when an API-key caller omits it. (Ignored when authenticating via a dashboard session.)

Reading the request id from a response

Every response carries a server-side request id in theX-Request-ID header. The clients copy that value onto every error they raise as request_id / requestId. When you file a support ticket, paste it.

BASH
curl -i -X POST "$API/memory/add" \
-H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d '{"text":"hello"}' | grep -i x-request-id

Idempotent retries

The memory routes are designed so that retrying a recently-failedadd with the exact same text does not create a duplicate — the deduplicator on the server collapses semantically identical inserts. bulkAdd takes an explicit deduplicate flag (default true) for the same reason.

What you do not need to do
You do not need to mint your own idempotency key for memory writes. If two retries land on the server, the second one returns a skipped result instead of a duplicate row.

A retry policy that works for both clients

Build retry logic against the typed errors. The same shape works in Python and TypeScript.

  1. Retry up to 3 times on RateLimitError and ServerError.
  2. For RateLimitError, sleep for the value the error reports in seconds, then retry.
  3. For ServerError, exponential backoff (e.g. 0.5s, 1s, 2s) with jitter.
  4. Never retry on AuthError, ValidationError, or NotFoundError — those are caller bugs.

Sizes, limits, and pagination

SurfaceLimitWhat happens past it
bulkAdd items50 per callServer rejects with HTTP 400; SDKs raise ValidationError before the call.
query k1–50 (default 5)Values outside [1, 50] are rejected with HTTP 422 ValidationError. There is no silent clamping — send a number in range.
compose max_tokensCaller-definedWhen the budget is exhausted the response sets truncated:true so you know to widen the window or trim memories.
forget idsServer-boundedPass them in batches; the response returns the ids that were actually deleted.

Timeouts you should set yourself

Both clients default to a 30-second timeout per call. For interactive surfaces you want a shorter timeout; for background workers you may want longer. The constructors accept this as timeout (Python) and timeoutMs (Node).

PYTHON
MemorySyncClient(api_key="...", base_url="...", timeout=10.0) # seconds
TYPESCRIPT
new MemorySyncClient({ apiKey: "...", baseUrl: "...", timeoutMs: 10_000 });

Environment discipline

  • Never inline an API key in source. Read it from MEMORYSYNC_API_KEY or your secret manager.
  • Set baseUrl per environment; use a staging key against a staging base URL and a live key against the production base URL.
  • If you scope by project on the dashboard, set projectId in the client constructor — do not pass it in every method call.