Personal access keys

A personal access key (PAK) lets you use MemHub from your own code — an agent you're building, a script, an IDE assistant — without logging in through the browser each time. It authenticates as you, so everything it does happens in your workspace and under your name.

Keys look like mhk_…. You mint, list, and revoke them with the API calls below — a point-and-click Settings → Developer → Access keys page is on the way.


When to use one

  • You're building an agent that should search or write your team's memory in its own loop (via the MCP server or the REST API).
  • You're wiring MemHub into a tool that can't do an interactive login — a CI job, a server, a coding assistant.

A key is a seat, not a bulk credential: it runs at roughly one person's throughput. If you need to serve many end-users at high volume, that's the Memory API (a separate product with its own keys), not a personal key.

MemHub vs. the Memory API

A personal key reads and writes MemHub's own team memory — the brains, facts, and artifacts you see in the app — over the MCP server or the REST API below. It can also mint and manage your Memory API keys. But it is not itself a credential for the Memory API's data: reading that product's stored memories uses an xtk_ API key, not your mhk_ key. Pointing a control-plane token at the data plane would blur the line between the two products, so that door is closed on purpose.

Create a key

Mint a key with one API call, authenticated with your MemHub login ($MEMHUB_JWT — the bearer token from your signed-in session):

curl -X POST https://api.memhub.xtrace.ai/v1/developer/access-tokens \
  -H "Authorization: Bearer $MEMHUB_JWT" \
  -H "Content-Type: application/json" \
  -d '{"label": "research-agent", "scopes": ["memory:read", "memory:write"]}'
# → { "secret": "mhk_…" }   — shown once; copy it now
  • Label each key (laptop, ci, research-agent) so you can tell them apart.

  • Pass "scopes": ["memory:read"] for a read-only key (see Scopes), "default_org_id" to pin it to one org, or "expires_at" to set an expiry.

  • The secret is returned once — store it in a secret manager or an env var:

    export MEMHUB_API_KEY="mhk_…"
    

You can hold up to 5 keys at a time. Minting requires a real login — a key can't mint another key.

Use a key

Full endpoint list: the PAK API reference documents every MCP tool and REST endpoint a key can call, with request/response shapes.

With an MCP client (recommended)

Point any MCP client — Claude Code, Cursor, the Claude Agent SDK, LangChain, etc. — at MemHub with the key as a bearer header:

{
  "mcpServers": {
    "memhub": {
      "url": "https://api.memhub.xtrace.ai/mcp-server/mcp",
      "headers": { "Authorization": "Bearer ${MEMHUB_API_KEY}" }
    }
  }
}

If your tool can only launch a local (stdio) MCP process, bridge to the hosted endpoint:

npx mcp-remote https://api.memhub.xtrace.ai/mcp-server/mcp \
  --header "Authorization: Bearer $MEMHUB_API_KEY"

From plain HTTP

The MCP endpoint is JSON-RPC over HTTP, so any language can call it. Two things to get right: send both Accept media types, and put the tool name/args under params.

curl -sX POST https://api.memhub.xtrace.ai/mcp-server/mcp \
  -H "Authorization: Bearer $MEMHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"search_memory","arguments":{"query":"onboarding decisions"}}}'

Over the REST API

Prefer plain REST to the MCP protocol? The same key works directly against MemHub's team-memory API — search, read, and write your team's facts, artifacts, and brains:

# search your team's facts
curl -sX POST https://api.memhub.xtrace.ai/v1/team/facts/search \
  -H "Authorization: Bearer $MEMHUB_API_KEY" \
  -H "X-Org-Id: <your-org-id>" \
  -H "Content-Type: application/json" \
  -d '{"query": "onboarding decisions"}'

Available today: /v1/team/facts, /v1/team/artifacts, and /v1/team/cbs (brains) — GET to list, POST …/search to search (both need memory:read); create / update / delete need memory:write. Same seat throughput and scopes as the MCP tools. Pass X-Org-Id to choose an org, or pin the key to one when you mint it.

In an agent loop

The payoff is the loop: search shared memory before answering, write new memory after. With the Anthropic SDK, hand the model the MCP server and it calls the tools itself:

import os
from anthropic import Anthropic

client = Anthropic()
resp = client.beta.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    messages=[{"role": "user", "content": "What did we decide about billing?"}],
    mcp_servers=[{
        "type": "url",
        "url": "https://api.memhub.xtrace.ai/mcp-server/mcp",
        "name": "memhub",
        "authorization_token": os.environ["MEMHUB_API_KEY"],
    }],
    betas=["mcp-client-2025-04-04"],
)
print(resp.content)

Scopes

Keys carry a coarse scope so you can limit a key's blast radius:

ScopeCan
memory:readsearch memory (read-only)
memory:writeread and write memory, and manage developer API keys

A new key gets both by default. Choose read-only when a key only needs to search: the write gate is enforced everywhere — the MCP write tools and the REST write endpoints both reject a memory:read-only key — so a leaked read-only key can search but can't change anything or touch your API keys.

Rate limits

A key runs at one seat's throughput, and your whole org is capped at your purchased seats' worth. If you go too fast you'll get 429 Too Many Requests with a Retry-After header — back off for that many seconds and retry. This is a product boundary, not a performance limit: a single agent working at human pace won't hit it.

Rotate a key

To rotate without downtime: create a new key, deploy it, then revoke the old one. Because you can hold several keys at once, the old one keeps working until you remove it — no gap.

Revoke a key

List your keys with GET /v1/developer/access-tokens, then revoke one by id:

curl -X DELETE https://api.memhub.xtrace.ai/v1/developer/access-tokens/<token-id> \
  -H "Authorization: Bearer $MEMHUB_JWT"

Revocation takes effect within about a minute across the MCP server and the API. Revoke a key the moment a laptop or environment it lived on is gone. (A Settings page for this is on the way.)

Good to know

  • A key is tied to you. If you leave the org, your keys stop working — so shared automation should run on a dedicated account, not a personal key.
  • A key can't create another key — minting keys always requires a real login. It also can't touch org settings, billing, or other people's data.
  • Keys are stored hashed; MemHub never sees your secret again after you copy it, which is why a lost secret means minting a new key, not recovering the old.