Skip to main content
Docs
Memory API

Memory API

Read and manage your users' memories through the Platform API.

The Memory API exposes your organization's user memories as a single resource on api.elyxir.ai. You can list, add, update, delete, and incrementally sync memories for any member of your organization. All responses are formatted as flat MemoryItem objects — the internal architecture is intentionally not surfaced.

Rollout in progress: the Memory API authenticates with OAuth JWT bearer tokens. It is available today in sandbox and staging environments; production availability is rolling out.

Authentication

The Memory API uses the same Platform API authentication as the API Keys and Usage endpoints. Every request requires two credentials:

HeaderRequiredDescription
AuthorizationYesBearer <platform-credential>
X-Organization-IdYesYour organization UUID
Content-TypeFor POST/PATCHMust be application/json

The platform credential is the RS256 OAuth JWT issued by the Elyxir authorization server. The organization UUID is available from the OAuth userinfo endpoint.

All responses include Cache-Control: no-store.

The MemoryItem Object

Every response wraps memories as MemoryItem objects:

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "content": "Prefers concise answers with code examples",
  "category": "preference",
  "createdAt": "2026-07-18T10:00:00.000Z",
  "updatedAt": "2026-07-18T10:00:00.000Z"
}
FieldTypeDescription
idstring (UUID)Unique identifier for this memory
contentstringThe memory text
categorystringOne of the six category values below
createdAtstring (ISO 8601)When this memory was first recorded
updatedAtstring (ISO 8601)When this memory was last changed

Category Values

ValueMeaning
identityWho the user is — name, role, background
preferenceStated preferences and working style
goalThings the user is working toward
projectProject-specific context
relationshipConnections to people, teams, or systems
constraintHard limits or rules the user has stated

If you POST a memory without a category, or with an unrecognized value, the category is omitted (the memory is still saved).

In rare cases a save is folded into an existing memory rather than creating a new one; the response is then 200 {"ok": true} (no memory object), or a minimal {"memory": {"id", "content"}}. Treat the absence of a full memory object as "saved, nothing new to store."

User Override

By default, every request operates on the memory of the user who owns the credential. To act on behalf of a different member of your organization, include a user query parameter (GET/PATCH/DELETE) or a user body field (POST) containing the target user's UUID. The target user must be a member of the organization identified by X-Organization-Id.

Project Memory

Projects have a shared memory pool: memories contributed in a project's context are visible to every project collaborator. To work with a project's pool instead of a user's memories, pass the project's UUID:

  • GET /api/v1/memory?project=<uuid> — list (or incrementally sync, with since) the project's shared memories. Requires access to the project.
  • POST /api/v1/memory with a project field — contribute a memory to the pool. Requires editor access to the project.

The project selector cannot be combined with the user override. Editing and deleting through /api/v1/memory/{id} always applies to memories you contributed yourself.

Endpoints

List Memories

GET https://api.elyxir.ai/api/v1/memory

Returns all active memories for the user. For incremental sync, pass a since cursor from a previous response.

Query Parameters

ParameterRequiredDescription
sinceNoCursor from a previous response. Returns only memories changed since that point, plus a deleted array of IDs to remove locally.
userNoUUID of an org member to act on behalf of (defaults to key owner)
# Full pull
curl https://api.elyxir.ai/api/v1/memory \
  -H "Authorization: Bearer <credential>" \
  -H "X-Organization-Id: 00000000-0000-0000-0000-000000000000"
 
# Incremental pull
curl "https://api.elyxir.ai/api/v1/memory?since=2026-07-18T10%3A00%3A00.000Z" \
  -H "Authorization: Bearer <credential>" \
  -H "X-Organization-Id: 00000000-0000-0000-0000-000000000000"

Full Response (no since)

{
  "memories": [
    {
      "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "content": "Prefers concise answers with code examples",
      "category": "preference",
      "createdAt": "2026-07-18T10:00:00.000Z",
      "updatedAt": "2026-07-18T10:00:00.000Z"
    }
  ],
  "cursor": "2026-07-18T10:00:00.000Z"
}

Incremental Response (with since)

{
  "memories": [
    {
      "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
      "content": "Working on a TypeScript monorepo project",
      "category": "project",
      "createdAt": "2026-07-18T11:00:00.000Z",
      "updatedAt": "2026-07-18T11:00:00.000Z"
    }
  ],
  "deleted": ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
  "cursor": "2026-07-18T11:00:00.000Z"
}

The deleted array contains IDs that were removed since the last sync and should be dropped from local storage. The deleted field is only present on incremental responses.

Get a Memory

GET https://api.elyxir.ai/api/v1/memory/{id}

Returns a single memory by ID.

curl https://api.elyxir.ai/api/v1/memory/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer <credential>" \
  -H "X-Organization-Id: 00000000-0000-0000-0000-000000000000"
{
  "memory": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "content": "Prefers concise answers with code examples",
    "category": "preference",
    "createdAt": "2026-07-18T10:00:00.000Z",
    "updatedAt": "2026-07-18T10:00:00.000Z"
  }
}

Add a Memory

POST https://api.elyxir.ai/api/v1/memory

Adds a new memory. Returns the saved memory as a MemoryItem.

Request Body

FieldTypeRequiredDescription
contentstringYesThe memory text. Must be non-empty.
categorystringNoOne of the six category values. Omitted or unrecognized values are silently dropped.
userstring (UUID)NoTarget user UUID (must be an org member)
curl -X POST https://api.elyxir.ai/api/v1/memory \
  -H "Authorization: Bearer <credential>" \
  -H "X-Organization-Id: 00000000-0000-0000-0000-000000000000" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Prefers TypeScript over JavaScript",
    "category": "preference"
  }'
{
  "memory": {
    "id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
    "content": "Prefers TypeScript over JavaScript",
    "category": "preference",
    "createdAt": "2026-07-18T12:00:00.000Z",
    "updatedAt": "2026-07-18T12:00:00.000Z"
  }
}

Update a Memory

PATCH https://api.elyxir.ai/api/v1/memory/{id}

Updates the content and/or category of a memory. At least one field must be provided.

Note: Optimistic-concurrency conflict detection (409 response with a baseUpdatedAt field) is shipping in a forthcoming release. When available, you can pass baseUpdatedAt matching the updatedAt of the memory you read, and a 409 will be returned if another writer changed the record since then.

Request Body

FieldTypeRequiredDescription
contentstringNoNew content text (must be non-empty if provided)
categorystringNoNew category value
curl -X PATCH https://api.elyxir.ai/api/v1/memory/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer <credential>" \
  -H "X-Organization-Id: 00000000-0000-0000-0000-000000000000" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Prefers concise TypeScript answers with working code examples"
  }'
{
  "memory": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "content": "Prefers concise TypeScript answers with working code examples",
    "category": "preference",
    "createdAt": "2026-07-18T10:00:00.000Z",
    "updatedAt": "2026-07-18T12:30:00.000Z"
  }
}

Delete a Memory

DELETE https://api.elyxir.ai/api/v1/memory/{id}

Deletes a memory. The operation is idempotent — deleting an already-deleted ID returns {ok: true} without error. Deleted IDs appear in the deleted array of subsequent incremental pulls.

curl -X DELETE https://api.elyxir.ai/api/v1/memory/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer <credential>" \
  -H "X-Organization-Id: 00000000-0000-0000-0000-000000000000"
{
  "ok": true
}

Incremental Sync

The cursor field returned by every GET is an opaque high-watermark string. Pass it back as ?since=<cursor> on your next request to receive only records that changed since that point.

Recommended sync loop:

  1. On first launch, call GET /api/v1/memory (no since). Store the cursor and all returned memories locally.
  2. On subsequent syncs, call GET /api/v1/memory?since=<stored-cursor>.
  3. Upsert each item in memories into local storage (the same ID may appear multiple times across syncs if it is updated repeatedly — always use the latest version).
  4. Remove any IDs in the deleted array from local storage.
  5. Save the new cursor value, replacing the previous one.

The deleted array is only present on incremental responses. On a full pull (no since), all returned memories are active and there is nothing to remove.

Rate Limits

The Memory API enforces a rate limit of 60 requests per minute per credential. Exceeding the limit returns 429 Too Many Requests with a Retry-After header indicating when the next request can be made.

Error Reference

All errors return a JSON body with an error string field.

{
  "error": "content is required"
}
StatusMeaning
400Bad request — missing/invalid X-Organization-Id header, missing or invalid content, unrecognized user UUID, or no fields provided to PATCH
401Missing, invalid, or expired authorization credential
403Account suspended, banned, or the credential does not belong to a member of the specified organization
404Memory ID not found, or the memory feature is not enabled for this organization
409Concurrent edit conflict (shipping in a forthcoming release; see PATCH note above)
429Rate limit exceeded — check the Retry-After header
500Internal server error
Memory API | elyxir