API

Memory API

The /v1/memhq/{add, search, ask} endpoints — the canonical surface for agent integrations.

Memory API

Three endpoints cover most agent use cases. They share the same authentication, the same identity model (user_id / group_id), and the same error envelope.

EndpointPurpose
POST /v1/memhq/addIngest a message, event, or document.
POST /v1/memhq/searchRetrieve memories relevant to a query.
POST /v1/memhq/askGet a synthesized answer with citations.

For the complete request and response schemas, see the interactive API reference.

Authentication

All three endpoints accept a project API key as a bearer token:

Authorization: Bearer mhq_live_...

Project keys are scoped to a single project and grant read and write access to memory. Use the dashboard's Settings → API Keys to create and rotate keys.

POST /v1/memhq/add

Ingest one or more messages into a per-user or group graph. Returns immediately with an episode_id; the actual extraction and indexing runs asynchronously (typically completing within 2-6 seconds — see Ingestion pipeline).

Request

FieldTypeRequiredDescription
user_idstringone ofThe per-user graph to ingest into.
group_idstringone ofThe group graph to ingest into.
messagesarrayyesChat-style messages. Each has role (user, assistant, system) and content.
metadataobjectnoArbitrary JSON attached to the episode.
wait_for_processingbooleannoHold the request open until extraction completes. Default false.

Exactly one of user_id or group_id is required. To ingest a turn that should land in both a user's private graph and a shared group graph, make two calls.

Example

episode = client.add(
    user_id="user_42",
    messages=[
        {"role": "user", "content": "I'm a vegetarian."},
        {"role": "assistant", "content": "Noted — I'll keep that in mind."},
    ],
    metadata={"channel": "support_chat"},
)
print(episode.id)
const episode = await client.add({
  userId: "user_42",
  messages: [
    { role: "user", content: "I'm a vegetarian." },
    { role: "assistant", content: "Noted — I'll keep that in mind." },
  ],
  metadata: { channel: "support_chat" },
});
console.log(episode.id);
curl https://api.memhq.ai/v1/memhq/add \
  -H "Authorization: Bearer $MEMHQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "user_42",
    "messages": [
      {"role": "user", "content": "I am a vegetarian."},
      {"role": "assistant", "content": "Noted — I will keep that in mind."}
    ],
    "metadata": {"channel": "support_chat"}
  }'

POST /v1/memhq/search

Hybrid (vector + lexical) retrieval over the project's memory.

Request

FieldTypeRequiredDescription
querystringyesThe query text.
user_idstringone ofSearch the per-user graph.
group_idstring | string[]one ofSearch one or more group graphs.
limitintegernoMax memories to return. Default 10, max 50.
include_supersededbooleannoInclude historical memories (auto-enabled for temporal questions).
filtersobjectnoConstrain on entity, time window, source, or custom metadata.

You can pass both user_id and group_id in the same call to search a user's private memory together with shared group context.

Response

{
  "memories": [
    {
      "id": "mem_01HZ...",
      "content": "Vegetarian.",
      "score": 0.91,
      "entities": [{ "id": "ent_user_42", "name": "User 42" }],
      "source_episode_id": "epi_01HZ...",
      "created_at": "2026-05-12T14:33:02Z",
      "status": "active"
    }
  ],
  "query_id": "qry_01HZ..."
}

POST /v1/memhq/ask

Retrieve, synthesize, and return an answer with citations. Use this when you want MemHQ to do the prompt engineering for you; use search when you want raw memories to feed into your own prompt.

Request

FieldTypeRequiredDescription
questionstringyesThe question to answer.
user_idstringone ofThe per-user graph to draw from.
group_idstring | string[]one ofGroup graphs to draw from.
style"terse" | "explanatory"noAnswer length. Default "explanatory".
include_supersededbooleannoAllow historical memories to inform the answer.

Response

{
  "text": "They prefer dark roast, no sugar.",
  "sources": [
    {
      "memory_id": "mem_01HZ...",
      "content": "Prefers dark roast coffee, no sugar.",
      "score": 0.94
    }
  ],
  "query_id": "qry_01HZ..."
}

Errors

All endpoints share a single error envelope:

{
  "error": "user_id_or_group_id_required",
  "code": 400,
  "correlationId": "req_01HZ..."
}

Common errors:

CodeWhen
400Missing required field, or both user_id and group_id omitted.
401Missing or invalid Authorization header.
403API key is valid but doesn't have access to the requested graph.
404Project or graph does not exist.
429Rate limit exceeded. See X-RateLimit-Reset.
5xxServer error — retry with exponential backoff.