Skip to main content

Endpoint

POST /v1/memories/add

Authentication

Authorization: ApiKey mem_...

Headers

HeaderRequiredNotes
AuthorizationYesApiKey mem_...
Content-TypeYesapplication/json
Idempotency-KeyNoReplays the same queued response for duplicate writes

Request body

{
  "external_user_id": "customer-123",
  "agent_id": "support-bot",
  "messages": [
    {
      "role": "user",
      "content": "Please remember that I prefer weekly summaries."
    }
  ],
  "metadata": {
    "source": "chat"
  }
}

Schema

FieldTypeRequiredNotes
external_user_idstringYesEnd-user identifier inside your tenant
agent_idstring | nullNoOptional agent identifier
messagesConversationMessage[]YesAt least one message
metadataobjectNoArbitrary JSON object

ConversationMessage

FieldTypeRequired
role"user" | "assistant" | "system"Yes
contentstringYes

Response headers

HeaderMeaning
X-MemoryOS-Quota-ModeCurrent tenant mode: FULL, PASSTHROUGH, DEGRADED_RETRIEVE, or BLOCKED
X-MemoryOS-Budget-RemainingRemaining quota percentage as a decimal string
X-MemoryOS-Quota-ResetNext reset timestamp, if set
X-MemoryOS-Circuit-StatusPlatform dependency status
X-MemoryOS-Processingnormal or delayed

Response: queued

{
  "job_id": "72a20629-a76d-4a18-ab36-1c2778ba21d0",
  "status": "queued",
  "blocked_reason": null,
  "nothing_to_extract": false,
  "retry_after_seconds": null,
  "budget_remaining_pct": 0.9134,
  "processing_eta_seconds": null,
  "processing_status": "normal",
  "request_id": "c3d4fd63-77ff-48b6-9316-6bcbadf9476b",
  "timestamp": "2026-04-05T09:23:40.077265Z"
}

Response: blocked by the quality gate

The status value is usually the layer that blocked the request.

Example: L2

{
  "job_id": null,
  "status": "L2",
  "blocked_reason": "low_quality",
  "retry_after_seconds": null,
  "budget_remaining_pct": 0.9134,
  "request_id": "11111111-2222-3333-4444-555555555555",
  "timestamp": "2026-04-17T09:30:00Z"
}
Possible blocked status values:
  • L1
  • L2
  • L3
  • L4
  • blocked (internal gate fallback)

Nothing to extract

Some conversations pass the quality gate but contain no durable user memory. Examples:
  • greetings
  • acknowledgements
  • one-word replies
  • off-topic questions
This is not an error. It means the conversation was valid but contained nothing useful to store. SDKs expose this as result.nothing_to_extract / result.nothingToExtract.
result = mem.add(messages=messages, external_user_id="user_123")

if result.was_stored:
    print("Memory queued")
elif result.nothing_to_extract:
    print("Conversation had no storable information")
For tenants with domain schemas enabled, add() still uses this same endpoint. Domain-specific extraction runs internally after the general memory path.

Response: passthrough

When the tenant is in passthrough mode, MemoryOS accepts the call path but does not persist a memory write.
{
  "job_id": null,
  "status": "passthrough",
  "blocked_reason": null,
  "retry_after_seconds": null,
  "budget_remaining_pct": 0.0,
  "request_id": "11111111-2222-3333-4444-555555555555",
  "timestamp": "2026-04-17T09:30:00Z"
}

Idempotency-Key

Use Idempotency-Key when your application may retry the same write request. Example:
Idempotency-Key: 8b7f95f1-a98c-4d43-b321-889e881d29b8
MemoryOS stores the queued response for that key and replays it for duplicate requests instead of creating a second job.