CognitiveX Docs

Memory

The remember, recall, update, and forget verbs plus the /api/memories management surface — store, search, list, and delete your iCog memories.

This is the contract reference for iCog memory. Two route groups make up the surface: the cognitive verbs (remember, recall, update, forget) that you use to write and read memories, and the /api/memories management routes that list, search, count, and delete them. Everything here is grounded in the live API at https://api.cognitivx.io.

Every endpoint requires authentication. Pass either Authorization: Bearer <key> or X-API-Key: <key>, where the key is an icog_-prefixed API key created at developers.cognitivx.io/keys, or a short-lived JWT access token. An icog_ value works in the Authorization: Bearer header too. Missing or invalid auth returns 401 with WWW-Authenticate: Bearer.

Endpoints

MethodPathPurpose
POST/api/rememberStore a new memory.
POST/api/recallSemantic + temporal search over your memories.
POST/api/updateReplace an existing memory's content.
POST/api/forgetSoft-delete a memory by id (verb form).
GET/api/memoriesPaginated list with an optional type filter.
GET/api/memories/{id}Fetch one memory by id.
GET/api/memories/countsCounts grouped by type.
GET/api/memories/pinnedAll foundational (pinned) memories.
POST/api/memories/searchHybrid keyword + semantic search.
POST/api/memories/bulk-deleteSoft-delete up to 500 memories.
DELETE/api/memories/{id}Soft-delete one memory (REST form).
DELETE/api/memories/wipeDelete all memories, or all of one type.

Memory types

memory_type is the one field worth understanding before you write. It is a fixed enum, and the four values you may write are:

TypeUse it for
semanticFacts, knowledge, decisions, architecture.
episodicEvents, sessions, what happened. Powers the chronological timeline.
proceduralSkills, how-tos, coding patterns.
foundationalPinned facts. Always injected into context, never evicted.

Omit memory_type on a write and iCog classifies the content for you. Pass an invalid value and you get 400 with the list of accepted values in detail.

The enum also contains system-only types — error, pattern, insight, reflective, meta, emergent — populated by the cognition and dream engines. They can appear in read responses, but do not write them. Passing one to remember or update is rejected as an invalid memory_type.

Tier and org behavior

  • Tier gate. POST /api/remember and POST /api/update require an awakened tier account or higher for personal callers. Below that you get 403 with {"error":"tier_insufficient", ..., "required_tier":"awakened", "upgrade_url":"/settings"}. recall, forget, and all /api/memories reads and deletes have no tier gate. Org members are entitled through their seat and skip the personal tier check.
  • Org isolation. Every endpoint resolves the effective owner as the active org account when one is selected (via the optional X-Org-ID header on /api/memories/*), otherwise the caller. Reads and writes then target the org's shared store. Cross-user and cross-org access is always masked as 404, never 403.
  • Quota. Writes (remember, update, pinning) return 429 with a quota detail body when the account's memory capacity is exceeded.

The TypeScript SDK is @cognitivx/sdk. The cognitive verbs live in the memory namespace; the management routes live in the memories namespace. Call configureApiClient once, then call the namespaced functions; failures throw ApiError.


Remember a memory

Store a new memory. This is the single write entry point for facts, events, skills, and pinned facts.

POST /api/remember · Authorization: Bearer <key> or X-API-Key. Personal (non-org) callers must be awakened tier or higher.

FieldTypeRequiredDescription
contentstringyesThe memory text to store.
memory_typestring | nullnoOne of semantic, episodic, procedural, foundational. Omit to let iCog classify. Do not pass the system-only types.
agent_slugstring | nullnoIdentifies the writing agent. When set, the write is stamped to that agent (private agent visibility) and is read back only by recall calls that pass the same agent_slug.
deepbooleannoDefault false. When true, the response is an SSE stream: iCog searches related memories, classifies the content as new, duplicate, or refinement, then writes or skips. The final event (kind="done") carries memory_id and the action taken.
curl -X POST https://api.cognitivx.io/api/remember \
  -H "Authorization: Bearer $ICOG_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content":"We chose asyncpg over SQLAlchemy for the iCog backend to keep pooled connections explicit.","memory_type":"semantic"}'
import { configureApiClient, memory } from '@cognitivx/sdk';

configureApiClient({ apiKey: process.env.ICOG_KEY });

const { memory_id } = await memory.remember({
  content:
    'We chose asyncpg over SQLAlchemy for the iCog backend to keep pooled connections explicit.',
  memory_type: 'semantic',
});
{
  "memory_id": "a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b"
}

Errors: 400 invalid memory_type, or a validation/anchor rejection from the store (foundational writes require a first-person anchor). 401 missing or invalid auth. 403 tier_insufficient (below awakened, personal caller). 429 memory quota exceeded. 500 unexpected storage error.


Recall memories

Semantic plus temporal search over your stored memories. This is the primary read path for "what do I know about X".

POST /api/recall · Authorization: Bearer <key> or X-API-Key. No tier gate.

FieldTypeRequiredDescription
querystringyesNatural-language search query.
limitintegernoMax memories to return. Default 10.
memory_typestring | nullnoRestrict to one type.
temporalstring | nullnoOptional hint to bias toward a time frame (for example, recency).
deepbooleannoDefault false. When true, the response is an SSE chain stream; the final event (kind="done") carries the curated memory list.
agent_slugstring | nullnoPass the same slug used at write time to read back that agent's private memories. Omit for the user-scoped view.
curl -X POST https://api.cognitivx.io/api/recall \
  -H "X-API-Key: $ICOG_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"why did we pick asyncpg","limit":5}'
import { configureApiClient, memory } from '@cognitivx/sdk';

configureApiClient({ apiKey: process.env.ICOG_KEY });

const { memories, count } = await memory.recall({
  query: 'why did we pick asyncpg',
  limit: 5,
});
{
  "memories": [
    {
      "id": "a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b",
      "text": "We chose asyncpg over SQLAlchemy for the iCog backend to keep pooled connections explicit.",
      "memory_type": "semantic",
      "age_days": 3,
      "created_at": "2026-06-13T18:04:22.512000+00:00",
      "occurred_at": null,
      "occurred_at_end": null,
      "occurred_precision": null,
      "similarity": 0.83,
      "temporal_context": null
    }
  ],
  "count": 1
}

The occurred_at* fields are event-time and are distinct from created_at (write-time). occurred_precision is one of instant, hour, day, week, month, range, or unknown. similarity is the vector match score.

Recall swallows internal errors and returns 200 with {"memories":[],"count":0} rather than a 5xx. Check count, not just the status code. Memories whose owner does not match the effective owner are filtered out by the cross-contamination guard.

Errors: 401 missing or invalid auth. 429 quota exceeded (rare on read).


Update a memory

Replace an existing memory's content. This soft-deletes the old row and stores a new one, preserving the original memory_type.

POST /api/update · Authorization: Bearer <key> or X-API-Key. Personal (non-org) callers must be awakened tier or higher.

FieldTypeRequiredDescription
memory_idstring (UUID)yesThe memory to replace. Must be owned by the caller (or the active org).
contentstringyesThe new content. memory_type is carried over from the original automatically.
curl -X POST https://api.cognitivx.io/api/update \
  -H "Authorization: Bearer $ICOG_KEY" \
  -H "Content-Type: application/json" \
  -d '{"memory_id":"a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b","content":"We chose asyncpg over SQLAlchemy for explicit pooled connections and lower overhead."}'
import { configureApiClient, memory } from '@cognitivx/sdk';

configureApiClient({ apiKey: process.env.ICOG_KEY });

const { old_memory_id, new_memory_id } = await memory.update(
  'a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b',
  'We chose asyncpg over SQLAlchemy for explicit pooled connections and lower overhead.',
);
{
  "old_memory_id": "a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b",
  "new_memory_id": "b2e4d3c5-6c7f-5a89-0b12-3d4e5f6a7b8c"
}

The new_memory_id differs from old_memory_id: re-embedding the new content mints a new row. The ownership lookup excludes already soft-deleted rows.

Errors: 400 invalid memory_id UUID, or a validation/anchor rejection on the new content. 401 missing or invalid auth. 403 tier_insufficient (below awakened, personal caller). 404 memory not found or not owned by the caller. 429 quota exceeded. 500 transient on the re-store.


Forget a memory

Soft-delete a single memory by id, verb form with a JSON body. Verifies ownership first.

POST /api/forget · Authorization: Bearer <key> or X-API-Key. No tier gate.

FieldTypeRequiredDescription
memory_idstring (UUID)yesThe memory to soft-delete. Must be owned by the caller (or the active org).
curl -X POST https://api.cognitivx.io/api/forget \
  -H "X-API-Key: $ICOG_KEY" \
  -H "Content-Type: application/json" \
  -d '{"memory_id":"a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b"}'
import { configureApiClient, memory } from '@cognitivx/sdk';

configureApiClient({ apiKey: process.env.ICOG_KEY });

const { forgotten } = await memory.forget('a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b');
{
  "memory_id": "a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b",
  "forgotten": true
}

On an internal delete failure this route still returns 200, but with {"memory_id":null,"forgotten":false}. Check the forgotten flag, not just the status code. For id-in-path deletion, use DELETE /api/memories/{id}.

Errors: 400 invalid memory_id UUID. 401 missing or invalid auth. 404 memory not found or not owned by the caller.


List memories

Paginated listing of stored memories with an optional type filter.

GET /api/memories · Authorization: Bearer <key> or X-API-Key. Optional X-Org-ID header scopes to org memory.

NameTypeRequiredDescription
memory_typestringnoFilter by one type. Invalid value returns 400.
limitintegernoMax results. Default 50, capped at 200.
offsetintegernoPagination offset. Default 0.
sortstringnorecent (default) or relevance.
curl "https://api.cognitivx.io/api/memories?memory_type=semantic&limit=20" \
  -H "X-API-Key: $ICOG_KEY"
import { configureApiClient, memories } from '@cognitivx/sdk';

configureApiClient({ apiKey: process.env.ICOG_KEY });

const { memories: rows, total, has_more } = await memories.list({
  memory_type: 'semantic',
  limit: 20,
});
{
  "memories": [
    {
      "id": "a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b",
      "content": "We chose asyncpg over SQLAlchemy for the iCog backend.",
      "memory_type": "semantic",
      "source": "icog:web",
      "source_label": "Chat",
      "tags": [],
      "created_at": "2026-06-13T18:04:22.512000+00:00",
      "updated_at": null,
      "access_count": 2,
      "display_text": "We chose asyncpg over SQLAlchemy for the iCog backend.",
      "canonical_url": null
    }
  ],
  "total": 1,
  "has_more": false
}

Each object also carries cognitive scores (wisdom_score, base_strength, plasticity, emotional_valence, experiential_weight), the attribution envelope (claimant_slug, claim_type, subject_kind, agent_visibility), and occurred_at* event-time fields. The human-relevant subset is shown above; the rest are present on the wire.

Errors: 400 invalid memory_type. 401 missing or invalid auth.


Get one memory

Fetch a single stored memory by id. The object is wrapped under memory.

GET /api/memories/{memory_id} · Authorization: Bearer <key> or X-API-Key.

NameTypeRequiredDescription
memory_idstring (UUID, path)yesThe memory id.
curl https://api.cognitivx.io/api/memories/a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b \
  -H "X-API-Key: $ICOG_KEY"
import { configureApiClient, memories } from '@cognitivx/sdk';

configureApiClient({ apiKey: process.env.ICOG_KEY });

const { memory: row } = await memories.get('a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b');
{
  "memory": {
    "id": "a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b",
    "content": "We chose asyncpg over SQLAlchemy for the iCog backend.",
    "memory_type": "semantic",
    "source": "icog:web",
    "source_label": "Chat",
    "tags": [],
    "created_at": "2026-06-13T18:04:22.512000+00:00",
    "updated_at": null,
    "access_count": 2,
    "canonical_url": null
  }
}

Errors: 400 invalid memory ID format. 401 missing or invalid auth. 404 memory not found or owned by another user.


Search memories

Hybrid keyword (full-text) plus semantic search, merged with reciprocal-rank fusion. Inputs are query-string params even though this is a POST.

POST /api/memories/search · Authorization: Bearer <key> or X-API-Key.

NameTypeRequiredDescription
querystringyesSearch query.
memory_typestringnoRestrict to one type.
limitintegernoMax results. Default 20.

The params go in the query string, not a JSON body, despite the POST method. The SDK builds this correctly; hand-written curl needs the params on the URL.

curl -X POST "https://api.cognitivx.io/api/memories/search?query=asyncpg&limit=10" \
  -H "X-API-Key: $ICOG_KEY"
import { configureApiClient, memories } from '@cognitivx/sdk';

configureApiClient({ apiKey: process.env.ICOG_KEY });

const { memories: hits } = await memories.search({ query: 'asyncpg', limit: 10 });
{
  "memories": [
    {
      "id": "a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b",
      "content": "We chose asyncpg over SQLAlchemy for the iCog backend.",
      "memory_type": "semantic",
      "source": "icog:web",
      "source_label": "Chat",
      "tags": [],
      "created_at": "2026-06-13T18:04:22.512000+00:00",
      "updated_at": null,
      "access_count": 2,
      "canonical_url": null
    }
  ],
  "total": 1,
  "has_more": false
}

has_more is always false: search does not paginate. The difference from /api/recall: search returns full stored-memory objects (content, source, tags), while recall returns a lighter result with similarity and event-time fields.

Errors: 400 invalid memory_type. 401 missing or invalid auth. 422 missing the required query param.


Bulk delete memories

Soft-delete up to 500 memories in one call by id list. Only ids owned by the caller are deleted; others are silently skipped.

POST /api/memories/bulk-delete · Authorization: Bearer <key> or X-API-Key.

FieldTypeRequiredDescription
memory_idsstring[] (UUIDs)yesUp to 500 ids. More than 500 returns 400.
curl -X POST https://api.cognitivx.io/api/memories/bulk-delete \
  -H "Authorization: Bearer $ICOG_KEY" \
  -H "Content-Type: application/json" \
  -d '{"memory_ids":["a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b","b2e4d3c5-6c7f-5a89-0b12-3d4e5f6a7b8c"]}'
{
  "deleted": 2
}

There is no SDK helper for bulk-delete. Call apiClient.post('/api/memories/bulk-delete', { memory_ids }) directly.

Errors: 400 more than 500 ids, or any id is not a valid UUID. 401 missing or invalid auth.


Delete one memory

Soft-delete a single memory by id. This is the REST-style counterpart to POST /api/forget.

DELETE /api/memories/{memory_id} · Authorization: Bearer <key> or X-API-Key.

NameTypeRequiredDescription
memory_idstring (UUID, path)yesThe memory to delete. Must be owned by the caller (or the active org).
curl -X DELETE https://api.cognitivx.io/api/memories/a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b \
  -H "Authorization: Bearer $ICOG_KEY"
import { configureApiClient, memories } from '@cognitivx/sdk';

configureApiClient({ apiKey: process.env.ICOG_KEY });

await memories.remove('a1f3c2d4-5b6e-4f78-9a01-2c3d4e5f6a7b');
{
  "message": "Memory deleted"
}

The DELETE is atomic on (id, user_id). Cross-user access is masked as 404, never 403.

The SDK types memories.remove(id) as returning { ok?: true }, but the server returns {"message":"Memory deleted"}. The call works; the typed shape is wrong. Do not rely on an ok field.

Errors: 400 invalid memory ID format. 401 missing or invalid auth. 404 memory not found or owned by another user.


Wipe memories

Nuclear delete of all memories, or all of one type. Irreversible from the API surface.

DELETE /api/memories/wipe · Authorization: Bearer <key> or X-API-Key.

NameTypeRequiredDescription
memory_typestringnoIf set, deletes only that type. If omitted, deletes everything for the effective owner.

Omitting memory_type wipes the entire store for the caller (or the active org). There is no undo. Guard this behind a confirmation in any UI.

curl -X DELETE "https://api.cognitivx.io/api/memories/wipe?memory_type=episodic" \
  -H "Authorization: Bearer $ICOG_KEY"
{
  "deleted": 42
}

There is no SDK helper for wipe. Note the param is on the query string, not a body.

Errors: 400 invalid memory_type. 401 missing or invalid auth.


Memory counts by type

Aggregate counts of stored memories grouped by type, plus an all total.

GET /api/memories/counts · Authorization: Bearer <key> or X-API-Key. No params.

curl https://api.cognitivx.io/api/memories/counts \
  -H "X-API-Key: $ICOG_KEY"
import { configureApiClient, memories } from '@cognitivx/sdk';

configureApiClient({ apiKey: process.env.ICOG_KEY });

const counts = await memories.counts();
{
  "counts": {
    "all": 128,
    "semantic": 71,
    "episodic": 44,
    "procedural": 9,
    "foundational": 4
  }
}

Which keys appear depends on what you have stored; all is the grand total used for list pagination.

The raw HTTP response nests under counts. The SDK memories.counts() is typed as Record<string, number> and omits that wrapper, so read the returned object's fields against your own runtime shape.

Errors: 401 missing or invalid auth.


List pinned memories

Return all foundational (pinned) memories — the facts always injected into session context. They are never evicted.

GET /api/memories/pinned · Authorization: Bearer <key> or X-API-Key. No params.

curl https://api.cognitivx.io/api/memories/pinned \
  -H "X-API-Key: $ICOG_KEY"
{
  "memories": [
    {
      "id": "c3f5e4d6-7d8a-6b90-1c23-4e5f6a7b8c9d",
      "content": "The user's name is Parsa and the active product is CognitiveX / iCog.",
      "memory_type": "foundational",
      "source": "icog:web",
      "source_label": "Chat",
      "tags": ["pinned"],
      "created_at": "2026-05-30T11:20:00+00:00",
      "updated_at": null,
      "access_count": 0,
      "canonical_url": null
    }
  ]
}

Foundational memories are created either by remember with memory_type: "foundational" or via the dedicated POST /api/memories/pin endpoint.

Errors: 401 missing or invalid auth.


  • Authentication & keys — how Bearer and X-API-Key auth resolve, and where to create icog_ keys.
  • Quickstart — your first remember and recall round trip.