SDK Endpoint Contract
Canonical HTTP routes, request/response shapes, and error semantics for SDK integrations.
This page is the canonical contract for the SDK HTTP surface under /api/sdk/v1/*.
Use it when implementing direct HTTP integrations, debugging SDK client behavior, or validating backward compatibility in CI.
Transport clarification:
- SDK default transport is this HTTP surface (
/api/sdk/v1/*). - SDK can optionally use MCP JSON-RPC (
/api/mcp) when you configuretransport: "mcp"(or pointbaseUrlat/api/mcp). - CLI commands are separate tooling and are not used by SDK runtime calls.
Base URL
https://memories.shEndpoint Matrix
| Group | Route | Methods | Auth |
|---|---|---|---|
| Health | /api/sdk/v1/health | GET | None |
| Runtime | /api/sdk/v1/context/get | POST | Bearer API key (mem_...) |
| Runtime | /api/sdk/v1/memories/add | POST | Bearer API key (mem_...) |
| Runtime | /api/sdk/v1/memories/search | POST | Bearer API key (mem_...) |
| Runtime | /api/sdk/v1/memories/list | POST | Bearer API key (mem_...) |
| Runtime | /api/sdk/v1/memories/edit | POST | Bearer API key (mem_...) |
| Runtime | /api/sdk/v1/memories/forget | POST | Bearer API key (mem_...) |
| Runtime | /api/sdk/v1/skills/files/upsert | POST | Bearer API key (mem_...) |
| Runtime | /api/sdk/v1/skills/files/list | POST | Bearer API key (mem_...) |
| Runtime | /api/sdk/v1/skills/files/delete | POST | Bearer API key (mem_...) |
| Graph | /api/sdk/v1/graph/status | GET, POST | Bearer API key (mem_...) |
| Graph | /api/sdk/v1/graph/trace | POST | Bearer API key (mem_...) |
| Graph | /api/sdk/v1/graph/rollout | GET, POST, PATCH | Bearer API key (mem_...) |
| Management | /api/sdk/v1/management/keys | GET, POST, DELETE | Legacy management auth (session/legacy path) |
| Management | /api/sdk/v1/management/tenants | GET, POST, DELETE | Legacy management auth (session/legacy path) |
Legacy aliases are still available:
/api/mcp/key/api/mcp/tenants
Authentication
Runtime + graph endpoints
Send your API key:
Authorization: Bearer mem_xxx
Content-Type: application/jsonManagement endpoints
/api/sdk/v1/management/* is currently a compatibility wrapper over legacy management routes and uses the same auth path as those endpoints.
If you are doing headless server-to-server management calls, validate auth flow in your environment before rollout.
Canonical Response Envelope
Every SDK v1 endpoint returns this envelope shape.
Success:
{
"ok": true,
"data": {},
"error": null,
"meta": {
"version": "2026-02-11",
"endpoint": "/api/sdk/v1/context/get",
"requestId": "3a4f3fc2-24ea-4e9e-ac61-6f2807f39584",
"timestamp": "2026-02-11T12:00:00.000Z"
}
}Failure:
{
"ok": false,
"data": null,
"error": {
"type": "validation_error",
"code": "INVALID_REQUEST",
"message": "Invalid request payload",
"status": 400,
"retryable": false,
"details": {
"field": "tenantId"
}
},
"meta": {
"version": "2026-02-11",
"endpoint": "/api/sdk/v1/memories/add",
"requestId": "8f2c34e5-2ed5-4a2f-92ea-c9d9faaf8db0",
"timestamp": "2026-02-11T12:00:00.000Z"
}
}Error Semantics
Error types
auth_error(401,403)validation_error(400,409)not_found_error(404)rate_limit_error(429)internal_error(500+)unknown_error(fallback classification)
Common error codes
| Code | Typical status | Notes |
|---|---|---|
MISSING_API_KEY | 401 | Runtime/graph endpoint called without Authorization |
INVALID_API_KEY_FORMAT | 401 | Bearer token format is invalid |
INVALID_API_KEY | 401 | Key hash not found |
API_KEY_EXPIRED | 401 | Key exists but expired |
RATE_LIMITED | 429 | Includes details.retryAfterSeconds |
INVALID_REQUEST | 400 | JSON shape/validation failed |
QUERY_REQUIRED | 400 | Empty query for search |
TENANT_ID_INVALID | 400 | Invalid scope.tenantId |
USER_ID_INVALID | 400 | Invalid scope.userId |
DATABASE_NOT_CONFIGURED | 400 | No active workspace DB for API key owner |
TENANT_DATABASE_NOT_CONFIGURED | 404 | Unknown AI SDK Project (tenantId) mapping (auto-provision may create this mapping when enabled) |
TENANT_DATABASE_NOT_READY | 409 | Tenant DB mapping exists but not ready |
TENANT_DATABASE_CREDENTIALS_MISSING | 404 | Tenant mapping missing credentials |
CANARY_ROLLOUT_BLOCKED | 409 | Quality gate blocked canary rollout |
INTERNAL_ERROR | 500 | Fallback internal error code |
LEGACY_MCP_KEY_ERROR | passthrough | Management keys wrapper error |
LEGACY_MCP_TENANTS_ERROR | passthrough | Management tenants wrapper error |
Scope Model
Runtime + graph requests accept optional scoped routing under scope:
{
"scope": {
"tenantId": "acme-prod",
"userId": "user_123",
"projectId": "github.com/acme/platform"
}
}tenantId: AI SDK Project selector (security/database boundary)userId: end-user scope insidetenantIdprojectId: optional repository context filter (not an auth boundary)
If tenantId is omitted, the request uses the API key owner's active workspace DB.
Request Constraints (Selected)
| Field | Constraint |
|---|---|
query | max 500 chars |
content (memories/add, memories/edit) | 1..8000 chars |
limit (context/get, search, trace) | 1..50 |
limit (memories/list) | 1..100 |
graphDepth | 0, 1, or 2 |
graphLimit | 1..50 |
tags[] | max 50 tags, each 1..120 chars |
paths[] | max 100 paths, each 1..300 chars |
category | 1..120 chars |
path (skills/files/*) | 1..400 chars |
content (skills/files/upsert) | 1..120000 chars |
Runtime Endpoint Contracts
POST /api/sdk/v1/context/get
Retrieve context bundle (rules + memories + trace).
Request:
{
"query": "deployment process",
"limit": 5,
"includeRules": true,
"includeSkillFiles": true,
"mode": "all",
"strategy": "baseline",
"graphDepth": 1,
"graphLimit": 8,
"scope": {
"tenantId": "acme-prod",
"userId": "user_123",
"projectId": "github.com/acme/platform"
}
}Defaults:
limit:5includeRules:trueincludeSkillFiles:truemode:allstrategy:baselinegraphDepth:1graphLimit:8
Response data:
mode,queryrules[]memories[]skillFiles[]workingMemories[]longTermMemories[]trace(strategy, rollout mode, fallback details, candidate counts)
POST /api/sdk/v1/memories/add
Create a memory.
Request:
{
"content": "Use canary rollout for graph retrieval changes",
"type": "rule",
"layer": "rule",
"tags": ["rollout", "graph"],
"paths": ["packages/web/src/app/**"],
"category": "ops",
"metadata": {
"source": "runbook"
},
"scope": {
"projectId": "github.com/acme/platform",
"userId": "user_123"
}
}Success status is 201.
Response data:
idmessagememory(structured memory record)
POST /api/sdk/v1/memories/search
Search memories by query.
Request:
{
"query": "rollout",
"type": "rule",
"layer": "rule",
"limit": 10,
"scope": {
"userId": "user_123"
}
}Response data:
memories[]count
POST /api/sdk/v1/memories/list
List recent memories with optional filters.
Request:
{
"type": "rule",
"layer": "rule",
"tags": "rollout",
"limit": 20,
"scope": {
"projectId": "github.com/acme/platform",
"userId": "user_123"
}
}Response data:
memories[]count
POST /api/sdk/v1/memories/edit
Update an existing memory.
Request:
{
"id": "mem_abc123",
"content": "Use canary then promote to full rollout after quality checks",
"tags": ["rollout", "canary"],
"scope": {
"userId": "user_123"
}
}Requires at least one editable field beyond id (content, type, layer, tags, paths, category, or metadata).
Response data:
idupdated: truemessage
POST /api/sdk/v1/memories/forget
Soft-delete a memory.
Request:
{
"id": "mem_abc123",
"scope": {
"userId": "user_123"
}
}Response data:
iddeleted: truemessage
POST /api/sdk/v1/skills/files/upsert
Create or update a scoped skill file.
Request:
{
"path": ".agents/skills/review/SKILL.md",
"content": "---\nname: review\n---\nUse strict checks.",
"scope": {
"tenantId": "acme-prod",
"userId": "user_123",
"projectId": "github.com/acme/platform"
}
}Response data:
skillFilecreatedmessage
POST /api/sdk/v1/skills/files/list
List scoped skill files.
Request:
{
"limit": 100,
"scope": {
"tenantId": "acme-prod",
"userId": "user_123",
"projectId": "github.com/acme/platform"
}
}Response data:
skillFiles[]count
POST /api/sdk/v1/skills/files/delete
Soft-delete a scoped skill file.
Request:
{
"path": ".agents/skills/review/SKILL.md",
"scope": {
"tenantId": "acme-prod",
"userId": "user_123",
"projectId": "github.com/acme/platform"
}
}Response data:
pathdeleted: truemessage
Graph Endpoint Contracts
GET|POST /api/sdk/v1/graph/status
Read graph health + rollout metrics for current scope.
GET query params:
topNodesLimittenantIduserIdprojectId
POST body:
{
"topNodesLimit": 10,
"scope": {
"tenantId": "acme-prod",
"userId": "user_123",
"projectId": "github.com/acme/platform"
}
}Response data includes:
enabled,flagshealth(ok|schema_missing)tables,countsrolloutshadowMetricsqualityGatealarmstopConnectedNodesrecentErrorssampledAtscope(resolved scope echo)
POST /api/sdk/v1/graph/trace
Trace retrieval behavior and graph expansion decisions.
Request is similar to context/get, but defaults differ:
strategydefault:hybrid_graphlimitdefault:10
Response data includes:
mode,includeRules,querystrategy:{ requested, applied }trace: rollout/fallback/candidate metricstiers: rule/working/long-term ID listsrecall[]: rank + source (baselineorgraph_expansion) + graph explainabilityrules[],memories[]
GET|POST|PATCH /api/sdk/v1/graph/rollout
Manage rollout mode.
GET:
- reads current rollout + quality gate + metrics summary
POST / PATCH request:
{
"mode": "canary",
"scope": {
"tenantId": "acme-prod",
"projectId": "github.com/acme/platform"
}
}mode must be one of:
offshadowcanary
Canary gate behavior:
POST/PATCH mode=canarycan return409withCANARY_ROLLOUT_BLOCKED- error
detailsincludesreasonCodes,qualityStatus, andwindowHours
Successful response data includes:
rolloutshadowMetricsqualityGatescope
Health Contract
GET /api/sdk/v1/health
Response data:
{
"status": "ok",
"service": "memories-sdk",
"schemaVersion": "2026-02-11"
}Management Endpoint Contracts
/api/sdk/v1/management/* currently wraps legacy /api/mcp/* responses into SDK envelopes.
GET|POST|DELETE /api/sdk/v1/management/keys
GET: current key status (hasKey,keyPreview,createdAt,expiresAt,isExpired)POST: rotate key withexpiresAtbodyDELETE: revoke key
POST request:
{
"expiresAt": "2027-01-01T00:00:00.000Z"
}GET|POST|DELETE /api/sdk/v1/management/tenants
GET: list AI SDK Projects (tenantIdmappings)POST: upsert AI SDK Project mappingDELETE: disable AI SDK Project mapping bytenantIdquery param
POST request:
{
"tenantId": "acme-prod",
"mode": "provision",
"metadata": {
"region": "us-east-2"
}
}Attach mode request:
{
"tenantId": "acme-prod",
"mode": "attach",
"tursoDbUrl": "libsql://example.turso.io",
"tursoDbToken": "token",
"tursoDbName": "example"
}DELETE example:
DELETE /api/sdk/v1/management/tenants?tenantId=acme-prodcURL Quick Reference
Context
curl -sS https://memories.sh/api/sdk/v1/context/get \
-H "Authorization: Bearer $MEMORIES_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query":"deployment",
"scope":{"tenantId":"acme-prod","userId":"user_123","projectId":"github.com/acme/platform"}
}'Add memory
curl -sS https://memories.sh/api/sdk/v1/memories/add \
-H "Authorization: Bearer $MEMORIES_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content":"Always run smoke tests before deploy",
"type":"rule",
"scope":{"tenantId":"acme-prod","userId":"user_123","projectId":"github.com/acme/platform"}
}'Graph rollout status
curl -sS "https://memories.sh/api/sdk/v1/graph/rollout?tenantId=acme-prod" \
-H "Authorization: Bearer $MEMORIES_API_KEY"Compatibility Notes
- Prefer
transport: "sdk_http"(or"auto") in SDK clients. - MCP JSON-RPC (
/api/mcp) remains available for MCP-native clients. - Breaking SDK HTTP changes will ship under a new prefix (
/api/sdk/v2/*).