> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bsyncs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Ingest

> Store text into episodic memory (Qdrant) and semantic memory (Neo4j knowledge graph).

<Note>**Cost:** 5 operations per call</Note>

## `POST /brain/ingest`

Processes a piece of text through the full ingestion pipeline:

1. **Deduplication** — skips the text if a near-identical chunk already exists (cosine similarity ≥ 0.92)
2. **Graph extraction** — extracts entities and relationships via spaCy (default) or LLMGraphTransformer (when `use_llm_extraction: true`)
3. **Semantic storage** — writes graph triples to Neo4j with embeddings for vector index lookup
4. **Episodic storage** — chunks the text via SemanticChunker and stores embeddings in Qdrant
5. **Working memory** — updates the session rolling topic vector in Redis (if `session_id` provided)

***

## Request body

```json theme={null}
{
  "text": "Sarah Jenkins is the Lead Software Engineer at Acme Corp.",
  "persona": "shared",
  "source": "user",
  "session_id": "session-abc",
  "use_llm_extraction": false,
  "metadata": {
    "document_id": "doc-001",
    "tags": ["team", "personnel"]
  }
}
```

| Field                | Type      | Required | Default    | Description                                                                                 |
| -------------------- | --------- | -------- | ---------- | ------------------------------------------------------------------------------------------- |
| `text`               | `string`  | ✓        | —          | The text to ingest. Minimum 1 character.                                                    |
| `persona`            | `string`  |          | `"shared"` | Memory sub-namespace within your user account.                                              |
| `source`             | `string`  |          | `"user"`   | Origin label: `"user"`, `"assistant"`, or `"document"`. Affects confidence scoring.         |
| `session_id`         | `string`  |          | `null`     | Enables working memory update for this session.                                             |
| `use_llm_extraction` | `boolean` |          | `false`    | Use LLMGraphTransformer (GPT-4.1) instead of spaCy for richer graph extraction. Costs more. |
| `metadata`           | `object`  |          | `null`     | Arbitrary key-value pairs stored alongside the memory.                                      |

***

## Response

```json theme={null}
{
  "facts_ingested": 3,
  "episodic_chunks": 1,
  "entities_extracted": 2,
  "triples_extracted": 3,
  "working_memory_updated": true,
  "msg": "Ingested 3 relations, 2 entities, 1 episodic chunks.",
  "latency_ms": 412.7
}
```

| Field                    | Type      | Description                                    |
| ------------------------ | --------- | ---------------------------------------------- |
| `facts_ingested`         | `int`     | Number of graph relationships stored in Neo4j. |
| `episodic_chunks`        | `int`     | Number of vector chunks stored in Qdrant.      |
| `entities_extracted`     | `int`     | Number of entity nodes created or updated.     |
| `triples_extracted`      | `int`     | Same as `facts_ingested`.                      |
| `working_memory_updated` | `boolean` | Whether the session topic vector was updated.  |
| `latency_ms`             | `float`   | Total processing time in milliseconds.         |

***

## Code examples

<CodeGroup>
  ```python Python SDK theme={null}
  from atlas_mem import AtlasMem

  brain = AtlasMem(api_key="atlas_...", base_url="https://api.bsyncs.com", user_id="user-123")

  # Basic ingest
  result = brain.add("Sarah Jenkins is the Lead Software Engineer at Acme Corp.")
  print(result.entities_extracted)  # 2
  print(result.triples_extracted)   # 3

  # With LLM extraction (richer graph, higher cost)
  result = brain.add(
      "The payment service uses Stripe for card processing and falls back to PayPal on failure.",
      source="document",
      metadata={"source_file": "architecture.md"},
  )
  ```

  ```python Python (requests) theme={null}
  import requests

  response = requests.post(
      "https://api.bsyncs.com/brain/ingest",
      headers={
          "x-api-key": "atlas_your_key_here",
          "Content-Type": "application/json",
      },
      json={
          "text": "Sarah Jenkins is the Lead Software Engineer at Acme Corp.",
          "persona": "shared",
          "source": "user",
          "session_id": "session-abc",
      }
  )
  print(response.json())
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.bsyncs.com/brain/ingest \
    -H "x-api-key: atlas_your_key_here" \
    -H "Content-Type: application/json" \
    -d '{
      "text": "Sarah Jenkins is the Lead Software Engineer at Acme Corp.",
      "persona": "shared",
      "source": "user"
    }'
  ```

  ```typescript TypeScript (fetch) theme={null}
  const response = await fetch("https://api.bsyncs.com/brain/ingest", {
    method: "POST",
    headers: {
      "x-api-key": "atlas_your_key_here",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      text: "Sarah Jenkins is the Lead Software Engineer at Acme Corp.",
      persona: "shared",
      source: "user",
    }),
  });

  const data = await response.json();
  console.log(data.entities_extracted); // 2
  ```
</CodeGroup>

***

## Batch ingest — `POST /brain/ingest/batch`

For ingesting multiple texts efficiently in one call.

<Note>**Cost:** 5 ops × number of items. Batch cost is deducted atomically upfront.</Note>

```json theme={null}
{
  "items": [
    {
      "text": "Sarah Jenkins is the Lead Software Engineer at Acme Corp.",
      "persona": "shared",
      "source": "user"
    },
    {
      "text": "Acme Corp's primary database is PostgreSQL.",
      "persona": "shared",
      "source": "document"
    }
  ]
}
```

**Batch size limits by tier:**

| Tier               | Max batch size |
| ------------------ | -------------- |
| Free               | 5              |
| Starter            | 20             |
| Pro                | 50             |
| Scale / Enterprise | 100            |

***

## Tips

<AccordionGroup>
  <Accordion title="When to use LLM extraction">
    Enable `use_llm_extraction: true` for long-form documents (technical specs, architecture docs, meeting notes) where entity relationships are complex. Keep it disabled for short conversational turns — spaCy is sufficient and much faster.
  </Accordion>

  <Accordion title="Source labels matter">
    Memories stored with `source: "user"` have higher confidence than `source: "assistant"` in conflict resolution. When two memories contradict each other for the same slot, the user-sourced one wins.
  </Accordion>

  <Accordion title="Metadata is searchable in the future">
    Any fields in `metadata` are stored alongside the vector. You can use them for custom filtering in direct API calls.
  </Accordion>
</AccordionGroup>
