Skip to Content
API Reference

API Reference

Engram exposes 8 core memory tools via the Model Context Protocol (MCP), accessed through the /mcp endpoint using Streamable HTTP transport. Connections that use an API key also get the vault and subscription tools. Every memory operation is also available as a plain REST endpoint under /api/v1 for backends and scripts that don’t speak MCP.

Requests authenticate with an API key (Authorization: Bearer engram_sk_live_...) or with the access token from OAuth sign-in.


create_conversation

Create a new conversation to store messages in.

Parameters

NameTypeRequiredDescription
titlestringNoTitle for the conversation
agent_idstringNoIdentifier for the agent that owns this conversation
tagsstring[]NoTags for filtering and organization
metadataobjectNoArbitrary key-value metadata

Response

{ "conversation_id": "conv_V1StGXR8_Z5jdHi6B-myT" }

Example

create_conversation title: "Weekly standup — March 23" agent_id: "support-bot-v2" tags: ["standup", "engineering"] metadata: { "team": "platform" }

append_messages

Append messages to a conversation. Messages are stored verbatim and automatically chunked and embedded for semantic search.

Parameters

NameTypeRequiredDescription
conversation_idstringYesThe conversation to append to
messagesMessageInput[]YesOne or more messages to append (min 1)

MessageInput:

NameTypeRequiredDescription
rolestringYesOne of: user, assistant, system, tool
contentstringYesThe message content (stored verbatim)
tool_call_idstringNoID of the tool call this message responds to
tool_namestringNoName of the tool that was called
metadataobjectNoArbitrary key-value metadata

Response

{ "appended": 2, "message_ids": [ "msg_V1StGXR8_Z5jdHi6B-myT", "msg_K2RtHYS9_A6keFj7C-nzU" ] }

Example

append_messages conversation_id: "conv_V1StGXR8_Z5jdHi6B-myT" messages: - role: "user" content: "Can you look up the customer's billing history?" - role: "assistant" content: "I'll check that now." - role: "tool" content: '{"invoices": [{"id": "inv_123", "amount": 99.00}]}' tool_name: "lookup_billing" tool_call_id: "call_abc" - role: "assistant" content: "They have one invoice for $99.00."

What happens on append

  1. Messages are inserted into the database with sequential ordering
  2. New messages are grouped into overlapping chunks (window of 5 messages, stride of 3)
  3. Each chunk is embedded using bge-base-en-v1.5 (768 dimensions)
  4. Vectors are upserted to the search index with conversation and organization metadata

Semantic search across all stored conversations. Returns matching chunk snippets with relevance scores. Each result contains the chunk_text window that Vectorize matched on, clipped to snippet_chars characters — call get_conversation with the returned start_sequence / end_sequence if you need the full structured messages.

Parameters

NameTypeRequiredDefaultDescription
querystringYes—Natural language search query
limitintegerNo5Max results (1–50)
conversation_idstringNo—Limit search to a specific conversation
tagsstring[]No—Filter by conversation tags
snippet_charsintegerNo1500Max characters of chunk_text per result (max 5000). Responses over the cap are suffixed with ...[truncated].

Response

{ "results": [ { "chunk_id": "chk_V1StGXR8_Z5jdHi6B-myT", "conversation_id": "conv_abc123", "chunk_text": "[user]: Can you look up the billing?\n[assistant]: I'll check that now.\n...", "score": 0.89, "start_sequence": 1, "end_sequence": 5 } ], "total": 1 }

Example

search query: "customer billing lookup" limit: 5

Results are ranked by cosine similarity. The chunk_text field contains the same [role]: content window that Vectorize matched on — enough context to decide which results are worth loading in full. If you need structured messages (role, tool_name, metadata, etc.), call get_conversation with the returned conversation_id and compute a message offset from start_sequence.

Why not return both? Earlier versions of the API returned chunk_text and the full Message[] for the same window, which doubled the response size and routinely pushed search responses past 10k tokens. The response now carries the chunk snippet only; structured messages are opt-in via get_conversation.


get_conversation

Retrieve a conversation with its full verbatim messages. Supports pagination for long conversations.

Parameters

NameTypeRequiredDefaultDescription
conversation_idstringYes—The conversation to retrieve
message_limitintegerNo100Max messages to return (1–500)
message_offsetintegerNo0Offset for pagination

Response

{ "conversation": { "id": "conv_V1StGXR8_Z5jdHi6B-myT", "title": "Weekly standup — March 23", "agent_id": "support-bot-v2", "tags": ["standup", "engineering"], "metadata": { "team": "platform" }, "message_count": 42, "created_at": "2026-03-23T10:00:00Z", "updated_at": "2026-03-23T10:30:00Z" }, "messages": [ { "id": "msg_xyz", "role": "user", "content": "Let's start with blockers...", "sequence": 1, "created_at": "2026-03-23T10:00:01Z" } ] }

Example

get_conversation conversation_id: "conv_V1StGXR8_Z5jdHi6B-myT" message_limit: 50 message_offset: 0

list_conversations

List conversations with filtering and sorting options.

Parameters

NameTypeRequiredDefaultDescription
limitintegerNo20Max conversations to return (1–100)
offsetintegerNo0Offset for pagination
agent_idstringNo—Filter by agent ID
tagsstring[]No—Filter by tags
sortstringNoupdated_atSort by: created_at, updated_at, message_count
orderstringNodescSort order: asc or desc

Response

{ "conversations": [ { "id": "conv_V1StGXR8_Z5jdHi6B-myT", "title": "Weekly standup — March 23", "agent_id": "support-bot-v2", "tags": ["standup"], "message_count": 42, "updated_at": "2026-03-23T10:30:00Z" } ], "total": 1 }

Example

list_conversations agent_id: "support-bot-v2" tags: ["engineering"] sort: "message_count" order: "desc" limit: 10

delete_conversation

Permanently delete a conversation and all its messages, chunks, and vector embeddings.

Parameters

NameTypeRequiredDescription
conversation_idstringYesThe conversation to delete

Response

{ "deleted": true }

Returns an error if the conversation is not found or doesn’t belong to your organization.


memory_status

Show how full the account’s memory is: lifetime storage used against the plan’s capacity, plus a monthly meter on plans that have one. Read-only.

Parameters

None.

Response

{ "tier": "free", "storage": { "used": 8240, "limit": 10000, "remaining": 1760, "bar": "[████████░░] 82%" }, "note": "Memory never expires — deleting conversations frees space. More room: upgrade at getengram.app/pricing." }

storage.limit is -1 on plans with unlimited storage, and remaining and bar are then left out. monthly (used, limit, remaining, bar) appears only on plans with a monthly limit. A brand-new account may also get an activation note. The bar strings are meant to be shown to the user as they are.


whoami

Show which Engram account the connection is using: organization name and email, tier, and how the connection authenticates. Read-only. Use it when you’re unsure which account memories are being saved to or searched from.

Parameters

None.

Response

Plain text, one fact per line:

Organization: Acme <dev@example.com> Org ID: org_… Tier: pro Auth: API key (key_…)

A connection that signs in with OAuth shows Auth: OAuth client (…) instead. A seat on a team account adds a Seat: line, and an account scheduled for deletion adds a warning line.


Tools on API-key connections

Connections that authenticate with an API key also get the secrets vault and subscription tools. Connections that sign in with OAuth, such as the Claude and ChatGPT connectors, get the 8 core tools only.

ToolDescription
resolve_vaultRetrieve encrypted vault entries by ID. Decryption happens client-side with your vault key
vault_setStore a named secret, encrypted client-side. The server never sees plaintext
vault_getRetrieve a named secret’s encrypted blob
vault_listList named secrets: names and metadata only, never values
vault_deleteDelete a named secret permanently
manage_subscriptionShow the current plan, or get a Stripe link to upgrade or manage billing. Only the account owner can upgrade or manage billing

Error Responses

When a tool encounters an error, it returns:

{ "error": "Conversation not found" }

Common errors:

ErrorCause
Conversation not foundInvalid conversation_id or doesn’t belong to your organization
401 UnauthorizedMissing or invalid API key
403 ForbiddenAPI key expired or revoked

REST API

Every memory operation is also available as a plain REST endpoint under /api/v1 — same behavior, same limits, same API key — for backends, scripts, and anywhere an MCP client isn’t practical. Base URL: https://mcp.getengram.app.

Requests to /mcp and /api/v1 count toward the API-requests meter shown on your dashboard .

EndpointMCP equivalentDescription
POST /api/v1/conversationscreate_conversationCreate a conversation. Body: { title?, agent_id?, tags?, metadata? } → 201 { conversation_id }
GET /api/v1/conversationslist_conversationsList conversations. Query: limit, offset, agent_id, tags (comma-separated), sort, order
GET /api/v1/conversations/:idget_conversationFetch a conversation with messages. Query: message_limit, message_offset
DELETE /api/v1/conversations/:iddelete_conversationDelete a conversation, its messages, and embeddings
POST /api/v1/messagesappend_messagesStore messages. Body: { conversation_id?, messages: [{ role, content, ... }] } — omit conversation_id to use the default memory
PATCH /api/v1/conversations/:id/messages/:messageId— (REST only)Update a message’s content in place. Body: { content } → 200 { updated, message }. The edit runs the same redaction pipeline as append, and the affected slice of the search index is rebuilt so recall matches the stored text. Requires the write scope.
GET /api/v1/searchsearchHybrid search. Query: q (required), limit, conversation_id, tags, project

Example

# Store a memory curl -X POST https://mcp.getengram.app/api/v1/messages \ -H "Authorization: Bearer engram_sk_live_..." \ -H "Content-Type: application/json" \ -d '{"messages":[{"role":"user","content":"We chose Postgres over DynamoDB for the billing service."}]}' # Search it later curl "https://mcp.getengram.app/api/v1/search?q=billing+database+choice" \ -H "Authorization: Bearer engram_sk_live_..."

REST error responses use conventional status codes: 400 invalid body/query, 401 bad key, 403 missing scope, 402 storage or plan limit, 404 not found, 429 monthly velocity limit.

Last updated on