---
title: "Retain memories"
method: POST
path: "/v1/default/banks/{bank_id}/memories"
tags: ["Memory"]
---

# Retain memories

`POST /v1/default/banks/{bank_id}/memories`

## Request

- Base URL: `https://hindsight.vectorize.io` (the document declares no server; this is the origin it was published from)
- URL: `https://hindsight.vectorize.io/v1/default/banks/{bank_id}/memories`
- Auth: none declared
- TypeScript: <https://skmtc.dev/vectorize/apis/hindsight-http-api/docs/v1/default/banks/:bank_id/memories/post.ts> (a function with typed inputs; its response is checked against the schema)

Retain memory items with automatic fact extraction.

This is the main endpoint for storing memories. It supports both synchronous and asynchronous processing via the `async` parameter.

**Features:**
- Efficient batch processing
- Automatic fact extraction from natural language
- Entity recognition and linking
- Document tracking with automatic upsert (when document_id is provided)
- Temporal and semantic linking
- Optional asynchronous processing

**The system automatically:**
1. Extracts semantic facts from the content
2. Generates embeddings
3. Deduplicates similar facts
4. Creates temporal, semantic, and entity links
5. Tracks document metadata

**When `async=true`:** Returns immediately after queuing. Use the operations endpoint to monitor progress.

**When `async=false` (default):** Waits for processing to complete.

**Note:** If a memory item has a `document_id` that already exists, the old document and its memory units will be deleted before creating new ones (upsert behavior).

## Path parameters

- `bank_id` string, required

## Headers

- `authorization` string, nullable

## Request body

- RetainRequest: Request model for retain endpoint.
  - `items` MemoryItem[], required
    - `content` union, required: The raw content to retain or extract from. Either a plain string or an ordered list of content blocks.
      - string
      - union[]
        - union
          - TextContentBlock: A run of text within a multimodal item, in the position the caller wrote it.
            - `type` 'text', required
            - `text` string, required
          - ImageContentBlock: An image within a multimodal item, in the position the caller wrote it.
            - `type` 'image', required
            - `source` Base64AttachmentSource, required: Inline attachment bytes, base64-encoded. The only source type in this version. ``url`` (server-side fetch) and ``blob_id`` (pre-uploaded handle) are the natural next ones, which is why this is modelled as a discriminated union on ``type`` rather than as bare fields.
              - …
          - FileContentBlock: A non-image attachment — a PDF, a spreadsheet — in its input position. This stays distinct from ``image`` because providers use different request parts for images and documents; retaining the caller's kind avoids guessing.
            - `type` 'file', required
            - `source` Base64AttachmentSource, required: Inline attachment bytes, base64-encoded. The only source type in this version. ``url`` (server-side fetch) and ``blob_id`` (pre-uploaded handle) are the natural next ones, which is why this is modelled as a discriminated union on ``type`` rather than as bare fields.
              - …
            - `filename` string, nullable: Original filename, passed to providers that show one to the model (e.g. OpenAI).
    - `timestamp` union: When the content occurred. Accepts an ISO 8601 datetime string (e.g. '2024-01-15T10:30:00Z'), null/omitted (defaults to now), or the special string 'unset' to explicitly store without any timestamp (use this for timeless content such as fictional documents or static reference material).
      - string, date-time
      - string
    - `context` string, nullable
    - `metadata` object, nullable
    - `document_id` string, nullable: Optional document ID for this memory item. Provide a distinct document_id per source document — items sharing a document_id are grouped into the same document. Auto-generated when omitted: if no item in the request has one, they all share one generated document (a request split into parts for size gets one per part); otherwise each item without one gets its own.
    - `entities` EntityInput[], nullable: Optional entities to combine with auto-extracted entities.
      - `text` string, required: The entity name/text
      - `type` string, nullable: Optional entity type (e.g., 'PERSON', 'ORG', 'CONCEPT')
    - `resolve_entities` boolean: Whether the names in 'entities' are resolved against the entities already in the bank. True (default) matches each name to a similar existing entity when it scores above the match threshold, so a name close to one already in the bank may resolve to that one instead of the one you wrote. False takes your names literally — an existing entity is reused only on a case-insensitive name match, any other name creates a new entity, and your names are never merged with each other. This applies only to the entities you supply here; auto-extracted entities are always resolved, since they are the extractor's guess at a name rather than yours. Ignored when 'entities' is omitted.
    - `tags` string[], nullable: Optional tags for visibility scoping. Memories with tags can be filtered during recall.
    - `observation_scopes` union: How to scope observations during consolidation. 'per_tag' runs one consolidation pass per individual tag, creating separate observations for each tag. 'combined' (default) runs a single pass with all tags together. 'shared' runs a single pass over one global, untagged scope, so memories consolidate together regardless of their tags — useful for deduplicating across volatile per-call provenance tags (e.g. per-session ids) while keeping those tags on the source facts. A list of tag lists runs one pass per inner list, giving full control over which combinations to use. An entry containing '*' is a glob matched against the memory's own tags — e.g. [['topic:*', 'user:*']] scopes by the memory's topic and user tags (including tags added by entity labels at retain) and ignores the rest; a scope whose globs match nothing is skipped. When omitted, the bank's default_observation_scopes applies ('combined' unless configured).
      - 'per_tag' | 'combined' | 'all_combinations' | 'shared'
      - array[]
        - string[]
    - `strategy` string, nullable: Named retain strategy for this item. Overrides the bank's default strategy for this item only. Strategies are defined in the bank config under 'retain_strategies'.
    - `update_mode` 'replace' | 'append', nullable: How to handle an existing document with the same document_id. 'replace' (default) deletes old data and reprocesses from scratch. 'append' concatenates new content to the existing document text and reprocesses.
  - `async` boolean: If true, process asynchronously in background. If false, wait for completion (default: false)
  - `document_tags` string[], nullable: Deprecated. Use item-level tags instead.
  - `operation_id` string, nullable: Optional client-supplied UUID used as the identity of an async retain operation. Re-submitting with the same operation_id returns the original operation and creates no new work, so retrying after a lost or timed-out acknowledgement will not enqueue a duplicate. Reusing an id that belongs to a different operation returns HTTP 409. Ignored for synchronous retain.

## Response `200`

Successful Response

- RetainResponse: Response model for retain endpoint.
  - `success` boolean, required
  - `bank_id` string, required
  - `items_count` integer, required
  - `async` boolean, required: Whether the operation was processed asynchronously
  - `operation_id` string, nullable: Operation ID for tracking async operations. Use GET /v1/default/banks/{bank_id}/operations to list operations. Only present when async=true. When items use different per-item strategies, use operation_ids instead.
  - `operation_ids` string[], nullable: Operation IDs when items were submitted as multiple strategy groups (async=true with mixed per-item strategies). operation_id is set to the first entry for backward compatibility.
  - `usage` TokenUsage: Token usage metrics for LLM calls. Tracks input/output tokens for a single request to enable per-request cost tracking and monitoring.
    - `input_tokens` integer: Number of input/prompt tokens consumed
    - `output_tokens` integer: Number of visible output/completion tokens generated (excludes reasoning/thoughts)
    - `total_tokens` integer: Total tokens (input + output, excludes thoughts)
    - `cached_tokens` integer: Cached/cache-read prompt tokens, when reported by the provider
    - `thoughts_tokens` integer: Reasoning/thinking tokens generated by the model. Billed at the output rate by some providers (e.g. Gemini 2.5+ family) but not surfaced in the visible response.

## Other responses

- `422`: Validation Error

## Changes

- **2026-10-04** `4fda98b75f63`: 1 warning, 6 info
  - removed the optional property `detail/items/url` from the response with the `422` status
  - added the new optional request property `items/items/resolve_entities`
  - added the new optional request property `operation_id`
  - added the new `shared` enum value to the request property `items/items/observation_scopes/anyOf[subschema #1]/`
  - …3 more
- **2026-05-15** `0d08f271b9db`: 4 info
  - added the new optional request property `items/items/update_mode`
  - added the optional property `detail/items/ctx` to the response with the `422` status
  - added the optional property `detail/items/input` to the response with the `422` status
  - added the optional property `detail/items/url` to the response with the `422` status

[Operation history](https://skmtc.dev/vectorize/apis/hindsight-http-api/changes/v1/default/banks/:bank_id/memories/post.md)

---

[API](https://skmtc.dev/vectorize/apis/hindsight-http-api.md) - [All operations](https://skmtc.dev/vectorize/apis/hindsight-http-api/llms.txt) - [OpenAPI document](https://skmtc.dev/vectorize/apis/hindsight-http-api/revisions/45e711cd0897?raw)
