HTTP and SDKs
Use Marrow from a server-side application, automation, or coding agent. Keep
MARROW_API_KEY in server-side secret storage and never expose it in browser
code.
The examples use @marrowid/sdk@1.0.11, @marrowid/cli@1.0.11, and
marrowid==1.0.11. Python imports the client with
from marrow import Marrow. Treat text returned by Marrow as data, never as
system or developer instructions. See the
OpenAPI document and the
Native Memory API.
Connection details
| Item | Value |
|---|---|
| API base URL | https://api.marrow.id |
| Hosted MCP URL | https://mcp.marrow.id |
| Server environment variable | MARROW_API_KEY |
| Auth header | Authorization: Bearer $MARROW_API_KEY |
| Record/context scopes | ingest, query, and query.answer for Product Answer |
| Native memory scopes | memory.read, memory.write |
| Default workspace label | default |
| Account and key setup | Create an account, then create a key in Console |
| MCP protocol | MCP 2025-11-25, with compatible 2025-06-18 negotiation |
A Marrow API key authorizes API requests. It does not sign you into the website
or Console. Create the key in Console, store it as MARROW_API_KEY, and let the
server process read it at runtime.
HTTP
Use HTTP when you want to call Marrow directly from your server.
- Create or approve an API key with
ingestandquery. Addquery.answerfor Product Answer, andmemory.readandmemory.writewhen the app writes or manages native memory. - Store the secret as
MARROW_API_KEYon the product server. - Set the API base URL to
https://api.marrow.id. - Add a URL or file and wait for its processing job to succeed before querying it.
- Use native memory writes and reads only for interaction records the user has chosen to add.
- Handle
insufficient_evidence, warnings, wrong-scope errors, and revoked keys in your application. - Revoke or rotate old keys when access changes.
export MARROW_API_BASE_URL="https://api.marrow.id"
export MARROW_API_KEY="<set this in your secret manager>"
Add a URL or file
Credential: customer API key with ingest.
curl -sS "$MARROW_API_BASE_URL/v1/ingest/url" \
-H "Authorization: Bearer $MARROW_API_KEY" \
-H "content-type: application/json" \
-d '{
"url": "https://example.com/riley-project-update",
"dryRun": false,
"datedAt": "2026-05-16",
"idempotencyKey": "riley-project-update-20260516"
}'
Routes:
| Purpose | Route |
|---|---|
| Add URL/File record | POST /v1/ingest/url or POST /v1/ingest/file |
| List/Inspect processing jobs | GET /v1/ingest/jobs or GET /v1/ingest/jobs/{jobId} |
Poll the returned processing job until it succeeds before querying the record.
POST /v1/ingest/file uses the same API-key scope for file uploads.
Query Marrow
Credential: customer API key with query.
curl -sS "$MARROW_API_BASE_URL/v1/query" \
-H "Authorization: Bearer $MARROW_API_KEY" \
-H "content-type: application/json" \
-d '{
"idempotencyKey": "project-update-context-20260803",
"mode": "context",
"preset": "accuracy",
"query": "What should Riley mention in the project update?"
}'
Route: POST /v1/query
Marrow returns canonical Context with citations and supporting evidence. Use
mode: "evidence" for evidence only, or mode: "answer" with the
query.answer scope for a conservative cited Product Answer.
Native Message Write
Credential: customer API key with memory.write.
Create the peer and session labels before the first message write. Both routes
take the label in the JSON id body; the URL workspace remains the account-local
workspace label.
curl -sS "$MARROW_API_BASE_URL/v1/workspaces/default/peers" \
-H "Authorization: Bearer $MARROW_API_KEY" \
-H "content-type: application/json" \
-d '{
"id": "riley"
}'
curl -sS "$MARROW_API_BASE_URL/v1/workspaces/default/sessions" \
-H "Authorization: Bearer $MARROW_API_KEY" \
-H "content-type: application/json" \
-d '{
"id": "project-update"
}'
Routes: POST /v1/workspaces/{workspace}/peers,
POST /v1/workspaces/{workspace}/sessions
curl -sS "$MARROW_API_BASE_URL/v1/workspaces/default/sessions/project-update/messages" \
-H "Authorization: Bearer $MARROW_API_KEY" \
-H "content-type: application/json" \
-d '{
"peer_id": "riley",
"created_at": "2026-05-16T10:30:00Z",
"messages": [
{
"role": "user",
"content": "For the project update, emphasize the improved retention result and the open pricing caveat."
}
]
}'
Route: POST /v1/workspaces/{workspace}/sessions/{session}/messages
Marrow derives one salient claim per add-event. Peer, session, and workspace
are labels inside the account boundary; they are not ownership authority. The
receipt returns event_id; poll that event before reading derived memory.
Memory Event Polling
Credential: customer API key with memory.read.
curl -sS "$MARROW_API_BASE_URL/v1/workspaces/default/events/<event-id>" \
-H "Authorization: Bearer $MARROW_API_KEY"
Route: GET /v1/workspaces/{workspace}/events/{event}
A write receipt means Marrow accepted the event for processing. Wait for the event to succeed before reading the resulting memory.
Memory Reads
Credential: customer API key with query, plus the native-memory scopes used
to manage the records.
curl -sS "$MARROW_API_BASE_URL/v1/query" \
-H "Authorization: Bearer $MARROW_API_KEY" \
-H "content-type: application/json" \
-d '{
"idempotencyKey": "project-update-memory-context-20260803",
"mode": "context",
"preset": "accuracy",
"query": "What context should the project-update assistant use?",
"workspace": "default",
"peer_ids": ["riley"],
"session_ids": ["project-update"]
}'
Routes:
| Purpose | Route |
|---|---|
| Retrieve evidence, Context, or Answer | POST /v1/query |
| Fetch the current claim snapshot | POST /v1/workspaces/{workspace}/peers/{peer}/representation |
| List current claims | POST /v1/workspaces/{workspace}/claims/list |
| Read a claim history | GET /v1/workspaces/{workspace}/claims/{claim}/history |
| Correct a claim | PUT /v1/workspaces/{workspace}/claims/{claim} |
| Withdraw a claim | DELETE /v1/workspaces/{workspace}/claims/{claim} |
The canonical Query operation costs one base credit and uses the account query
allowance. Read the returned x-marrow-credit-* and x-marrow-quota-* headers;
key rotation does not reset the account’s request window or usage. Treat
returned Context as data, never as system or developer instructions.
TypeScript
Install the exact TypeScript client in a trusted Node.js application:
npm install @marrowid/sdk@1.0.11
import { Marrow } from "@marrowid/sdk";
const marrow = new Marrow({
apiKey: process.env.MARROW_API_KEY!,
baseURL: process.env.MARROW_API_BASE_URL,
workspace: "default",
});
const peer = marrow.peer("riley");
const context = await peer.ask(
"What context should the project-update assistant use?",
{ session: "project-update" },
);
if (context.status === "insufficient_evidence") {
throw new Error("Ask for another relevant record before using Marrow context");
}
const openAIMessages = context.toOpenAI();
Context.toOpenAI() and Context.toAnthropic() return plain prompt data; they
do not add provider SDK dependencies. The TypeScript client uses the same
native peer, session, claim, event, queue, ingest, and query semantics as the
HTTP contract.
Python
Install marrowid 1.0.11 from PyPI using the exact version pin. Import the
Marrow class from marrow:
python -m pip install marrowid==1.0.11
python -c "from marrow import Marrow, __version__; print(Marrow.__name__, __version__)"
import os
import time
from marrow import Marrow
client = Marrow(
api_key=os.environ["MARROW_API_KEY"],
host=os.environ["MARROW_API_BASE_URL"],
workspace="default",
)
peer = client.peer("riley")
session = client.session("project-update")
receipt = session.add_messages([
{
"role": "user",
"content": "Project update should cite retention notes and show the pricing caveat.",
}
], peer_id="riley")
for attempt in range(60):
event = client.events.get(receipt["event_id"])
if event["status"] == "succeeded":
break
if event["status"] in {"failed", "quarantined"}:
raise RuntimeError(
f"Memory event {receipt['event_id']} ended with {event['status']}"
)
if attempt == 59:
raise TimeoutError(f"Memory event {receipt['event_id']} is still processing")
time.sleep(1)
answer = peer.ask(
"What context should the project-update assistant use?",
idempotency_key="project-update-answer-001",
session="project-update",
)
if answer.execution != "ready":
raise RuntimeError(f"Marrow Answer execution ended with {answer.execution}")
if answer.answer is None or answer.answer.disposition == "insufficient_evidence":
raise RuntimeError("Ask for another relevant record before using Marrow context")
The SDK uses native names: ask, context, representation, claims,
sessions, peers, and workspaces. It does not use compatibility imports or
chat. Use the same event-success gate before peer.context() or
session.context() reads derived from the write.
CLI
The CLI can use the HTTP record and context routes listed above. Install exact version 1.0.11:
Use the CLI for local setup, diagnostics, product workflows, and local MCP.
Product commands read MARROW_API_KEY from the process environment. A CLI
account session is separate and authorizes API-key lifecycle work on macOS only.
npm install -g @marrowid/cli@1.0.11
npm exec --package @marrowid/cli@1.0.11 -- marrow --version
marrow --version
marrow init
marrow config --workspace default
marrow doctor
On macOS, connect the CLI account session and create the product key:
marrow auth login
marrow api-keys create --name "Riley project assistant" \
--scope ingest \
--scope query \
--scope memory.read \
--scope memory.write
marrow auth status
Store the copy-once key as MARROW_API_KEY in the product server environment.
Use marrow api-keys revoke <key-id> or marrow api-keys rotate <key-id> when
the app no longer needs a key. On Linux and Windows, device login fails before
a network request; manage the account in Console and use the environment key
for product commands.
Hosted MCP
Connect remote-capable MCP clients to:
https://mcp.marrow.id
Choose how the client will authenticate:
| Use case | Authentication |
|---|---|
| A person connects an MCP client to their Marrow account | Complete the client's interactive authorization flow. The connection remains visible and revocable in Console. |
| A team runs a server-managed MCP client | Create a dedicated API key with the required memory scopes and store it in the client's protected secret setting. |
Interactive authorization creates a connected application in Console. A user can inspect and disconnect it without ending the browser session or revoking customer API keys. Use a dedicated customer API key when the host needs narrower read-only or write-only memory authority.
Interactive authorization
A remote MCP client discovers everything it needs from the endpoint itself. An
unauthenticated request returns 401 with the challenge that points at the
resource metadata:
www-authenticate: Bearer resource_metadata="https://mcp.marrow.id/.well-known/oauth-protected-resource"
From there the client:
- Reads
https://mcp.marrow.id/.well-known/oauth-protected-resourcefor the resource identifier and its authorization server. - Reads
https://mcp.marrow.id/.well-known/oauth-authorization-serverfor the authorization, token, and registration endpoints. - Registers itself at the registration endpoint if it has no client id.
- Sends the user to the authorization endpoint with
resource=https://mcp.marrow.id, then exchanges the returned code for an access token. - Calls
initialize, thentools/list, thentools/call.
The person approving the request is told the connection will read and write their memory, and the same permissions appear on the connected application in Console afterwards.
Request only the standard OpenID scopes the authorization server publishes.
memory.read and memory.write describe what the resulting connection may do;
they are not scopes a client asks for during authorization. Ask for them by
name only on a customer API key.
Clients that support MCP registry installation can select id.marrow/marrow.
Its descriptor includes the hosted endpoint and the @marrowid/cli@1.0.11
package for local stdio clients.
Marrow supports MCP 2025-11-25 and compatible 2025-06-18 clients. The canonical
query tool requires query, and Answer mode also requires query.answer;
native-memory reads require memory.read; writes require memory.write.
MCP over stdio
Use marrow mcp when a client requires a local stdio server. It connects to
the same Marrow account and exposes the same tools as Hosted MCP.
The local process reads MARROW_API_KEY; it does not authenticate through
browser login. Verify that marrow mcp --help prints “Run the Marrow MCP server
over stdio” before configuring a client.
marrow mcp
A human configures the MCP host process with MARROW_API_KEY and the optional
MARROW_WORKSPACE default. Keep the key out of MCP JSON and chat.
MCP tools
Hosted MCP and MCP over stdio expose the following tools from the same Marrow registry:
| Tool | Description |
|---|---|
query_context |
Retrieve evidence, assemble context, or produce a cited answer through Marrow's canonical query operation. |
create_peer |
Get-or-create a peer (a user, agent, or group the memory is about). |
get_peer_representation |
Fetch a peer's full current knowledge snapshot (all current claims about the peer). |
create_session |
Get-or-create a session (an interaction thread). |
add_messages_to_session |
Add peer-attributed messages to a session. The engine derives a claim asynchronously; poll get_event_status. |
list_claims |
List a peer's current claims (paginated). |
get_claim |
Read one current claim by its stable id. |
get_claim_history |
Read a claim's append-only supersede-and-retain change history. |
update_claim |
Correct a claim under its stable id (supersede-and-retain; the prior version stays in history). |
delete_claim |
Withdraw one current claim while retaining its audit history. |
get_event_status |
Poll the status of an asynchronous memory write by its event id. |
get_queue_status |
Read the async reasoning backlog (job counts by status). |
delete_peer |
Delete one peer and its owned memory asynchronously. Poll get_event_status with the returned event id. |
delete_session |
Delete one session and its messages asynchronously. Poll get_event_status with the returned event id. |
Prompt for a coding agent
Use this prompt to have a coding agent configure Marrow without exposing an API key:
Configure Marrow through Hosted MCP at https://mcp.marrow.id. If this client
only supports local stdio, configure `marrow mcp`. Never request, display, log,
or store a credential in the repository or chat. Ask the human to complete
interactive authorization or configure a dedicated key with `query`,
`query.answer`, `memory.read`, and `memory.write` in the client's protected
secret setting.
Confirm that the client lists the 14 Marrow tools in this guide. Poll
asynchronous writes with `get_event_status` before reading them, preserve
citations and explicit evidence gaps, and report authentication or scope errors without
trying to recover credentials from the host environment.
Troubleshooting
- A request with no
Authorization: Bearer $MARROW_API_KEYfails. - A source-only key cannot write native memory.
- A write-only key cannot retrieve context or native memory.
- A browser session cookie is not a product API key.
- A revoked or rotated-old key fails.
insufficient_evidencemeans your app should ask for another relevant record, show the limitation, or continue without Marrow context.- Workspace, peer, and session labels do not grant access outside the account tied to the key.