Getting Started
Your First Memory
This page walks through the real /memory/add contract: the required headers, accepted body fields, the route's server-side mutations, and the response shapes you can actually receive.
The request
BASH
curl -X POST https://api.memorysync.io/memory/add \
-H "X-API-Key: $MEMORYSYNC_API_KEY" \
-H "X-Project-ID: $MEMORYSYNC_PROJECT_ID" \
-H "X-End-User-ID: demo-user-001" \
-H "Content-Type: application/json" \
-d '{
"text": "User prefers dark mode and concise responses.",
"source": "chat",
"metadata": {"conversation_id": "conv-123"},
"deduplicate": true
}'Header contract
| Header | Required | Verified behaviour |
|---|---|---|
X-API-Key | yes for service auth | Resolved before the memory handler runs. |
Authorization: Bearer ... | alternative | JWT-authenticated callers act as the end user directly. |
X-Project-ID | usually yes | Globally enforced for project-scoped routes unless the API key already supplies project_id. |
X-End-User-ID | yes for service-auth memory calls | Resolves to the corresponding user. Ignored for dashboard JWT callers. |
Body fields the schema accepts
| Field | Meaning | Verified note |
|---|---|---|
text | Canonical memory body | Required unless you send content. After trimming, text must be at least 10 characters. |
content | Alias for text | Normalized into text by the schema. |
source | Origin label | Optional field on the request body. |
event_type | Trigger label | Optional field on the request body. |
tags | Semantic tags | Optional field on the request body. |
ttl_minutes | Retention hint | Optional integer >= 1. |
importance | Manual importance hint | Optional float from 0.0 to 1.0. |
metadata | Arbitrary JSON | Optional and preserved in the response. |
deduplicate | Duplicate handling flag | Defaults to true. |
user_id and project_id | Deprecated body fields | Ignored or overwritten by server-side auth and request state. |
What the route handler does
- Runs authentication, scope checks, and add-quota enforcement before processing the payload.
- If the org is over its add quota, silently returns
{"status":"ok"}without storing anything. - Resolves the effective end user. Service-auth callers must supply
X-End-User-IDorend_user_idin the body. - Overwrites client-supplied
user_id,environment, andproject_idwith trusted request context. - Runs the memory through the extraction pipeline before storing it.
- If a record was stored, emits the memory-created webhook and returns the first stored
MemoryResponse.
Response cases
| Case | HTTP | Body shape |
|---|---|---|
| Stored successfully | 201 | MemoryResponse. |
| Silent quota skip | 200 | {"status":"ok"}. |
| Extraction skip | 200 | {"status":"skipped","reason":...,"candidates_extracted":...}. |
| Missing project | 400 | {"code":"PROJECT_ID_REQUIRED",...}. |
| Missing end user | 400 | {"error":{"code":"MISSING_END_USER_ID",...}}. |
| Bad input | 422 | Structured validation error payload. |
Query the same user back
BASH
curl -X POST https://api.memorysync.io/memory/query \
-H "X-API-Key: $MEMORYSYNC_API_KEY" \
-H "X-Project-ID: $MEMORYSYNC_PROJECT_ID" \
-H "X-End-User-ID: demo-user-001" \
-H "Content-Type: application/json" \
-d '{
"query": "What response style does this user prefer?",
"k": 5
}'Common first-time snags
- Sending
project_idin the JSON body and expecting it to win. The handler overwrites it from request state. - Using an API key without
X-End-User-ID. Shared-key memory requests are rejected without an end-user identifier. - Sending fewer than 10 non-whitespace characters. The schema rejects it before the deeper service logic runs.
- Assuming add always returns
201. Silent quota mode and extraction skips both return200with different body shapes.