Skip to main content

Overview

Creating memories in Azen is straightforward: send text content to the API, and Azen handles encryption, storage, and vector embedding automatically.

Creating a Memory

1

Prepare your content

Memory content can be any text: user preferences, conversation context, facts, or notes.
2

Send POST request

Send a POST request to /api/v1/memory with your text content.
3

Receive confirmation

Get back a memory ID and confirmation that embedding is processing.

Basic Example

curl -X POST https://api.azen.sh/api/v1/memory \
  -H "azen-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "I love hiking in the mountains on weekends"
  }'
Response (201 Created):
{
  "status": "success",
  "memoryId": "550e8400-e29b-41d4-a716-446655440000",
  "createdAt": "2024-01-15T10:30:00.000Z",
  "embedding": "processing"
}
The embedding field will show "processing" initially. Embedding typically completes within seconds.

What Happens Behind the Scenes

When you create a memory, Azen performs several operations:
1

Encryption

Your text is encrypted using AES-256-GCM with a unique IV and authentication tag before storage.
2

Database Storage

The encrypted content, IV, and tag are stored in Postgres. The plaintext never touches disk.
3

Embedding Job

A background job is queued in BullMQ to generate vector embeddings for semantic search.
4

Vector Storage

Once processed, embeddings are stored in Pinecone, isolated from the encrypted plaintext.

Implementation Reference

From apps/api/src/routes/memory.ts:
// Generate encryption components
const memId = randomUUID();
const { ciphertext, iv, tag } = encryptText(text);

// Store encrypted memory
await db.insert(memory).values({
  id: memId,
  userId,
  organizationId,
  encryptedContent: ciphertext,
  iv,
  tag,
});

// Queue embedding job
await embeddingsQueue.add('embed', {
  jobId: jobRec.id,
  memoryId: rec.id,
  text: text, // Plaintext sent to worker, never persisted
  organizationId,
  userId,
});

Memory Content Guidelines

What to Store

Good memory content:
  • User preferences: “Prefers dark mode”
  • Conversation context: “Discussed AI ethics on March 5th”
  • Personal facts: “Lives in San Francisco, works remotely”
  • Behavioral patterns: “Usually asks about Python tutorials”
Avoid storing:
  • Sensitive credentials (use a secrets manager)
  • Large binary data (Azen is text-optimized)
  • Rapidly changing data (use a cache instead)
  • PII without user consent

Content Length

  • Minimum: 1 character (enforced by validation)
  • Maximum: No hard limit, but optimal performance under 2,000 characters
  • Recommended: 50-500 characters per memory for best search results
Longer memories are automatically chunked during embedding to maintain search quality.

Batch Memory Creation

For creating multiple memories, make parallel requests:
const memories = [
  "I prefer morning meetings",
  "I'm learning TypeScript",
  "I love jazz music"
];

const promises = memories.map(text =>
  fetch('https://api.azen.sh/api/v1/memory', {
    method: 'POST',
    headers: {
      'azen-api-key': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ text })
  })
);

const responses = await Promise.all(promises);
const data = await Promise.all(responses.map(r => r.json()));
console.log(data);
Respect rate limits when creating memories in batch. See Rate Limits for details.

Error Handling

Invalid Request (400)

Missing or empty text:
{
  "status": "invalid_request",
  "message": "Invalid request body",
  "code": 400
}
Solution: Ensure text field is present and non-empty.

Authentication Errors (401, 403)

See Authentication Guide for resolving auth issues.

Rate Limited (429)

{
  "status": "rate_limited",
  "message": "Rate limit exceeded for this API key",
  "code": 429
}
Solution: Implement exponential backoff or reduce request rate.

Server Error (500)

If memory creation fails:
{
  "status": "internal_server_error",
  "message": "Failed to create memory record",
  "code": 500
}
Solution: Retry with exponential backoff. If persists, contact support.

Checking Embedding Status

After creating a memory, check if embedding is complete:
curl -X GET https://api.azen.sh/api/v1/memory/{memoryId} \
  -H "azen-api-key: YOUR_API_KEY"
Response:
{
  "status": "success",
  "memory": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "content": "I love hiking in the mountains on weekends",
    "metadata": null,
    "createdAt": "2024-01-15T10:30:00.000Z",
    "embedded": true
  }
}
The embedded field indicates whether the memory is ready for semantic search.

Usage Tracking

Memory creation is automatically tracked:
  • Each successful POST /api/v1/memory increments memoryCount in usage metrics
  • Failed requests increment errorCount
  • Tracking is per organization, per API key, per day
See Usage Tracking for monitoring your usage.

Next Steps

Search Memories

Find memories using semantic search

List Memories

Retrieve all memories with pagination

Encryption Details

Learn how memory encryption works

Semantic Search

Understand vector embeddings

Build docs developers (and LLMs) love