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.
| Endpoint | Purpose |
|---|---|
POST /v1/memhq/add | Ingest a message, event, or document. |
POST /v1/memhq/search | Retrieve memories relevant to a query. |
POST /v1/memhq/ask | Get 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
| Field | Type | Required | Description |
|---|---|---|---|
user_id | string | one of | The per-user graph to ingest into. |
group_id | string | one of | The group graph to ingest into. |
messages | array | yes | Chat-style messages. Each has role (user, assistant, system) and content. |
metadata | object | no | Arbitrary JSON attached to the episode. |
wait_for_processing | boolean | no | Hold 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
| Field | Type | Required | Description |
|---|---|---|---|
query | string | yes | The query text. |
user_id | string | one of | Search the per-user graph. |
group_id | string | string[] | one of | Search one or more group graphs. |
limit | integer | no | Max memories to return. Default 10, max 50. |
include_superseded | boolean | no | Include historical memories (auto-enabled for temporal questions). |
filters | object | no | Constrain 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
| Field | Type | Required | Description |
|---|---|---|---|
question | string | yes | The question to answer. |
user_id | string | one of | The per-user graph to draw from. |
group_id | string | string[] | one of | Group graphs to draw from. |
style | "terse" | "explanatory" | no | Answer length. Default "explanatory". |
include_superseded | boolean | no | Allow 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:
| Code | When |
|---|---|
400 | Missing required field, or both user_id and group_id omitted. |
401 | Missing or invalid Authorization header. |
403 | API key is valid but doesn't have access to the requested graph. |
404 | Project or graph does not exist. |
429 | Rate limit exceeded. See X-RateLimit-Reset. |
5xx | Server error — retry with exponential backoff. |