Skip to main content

API Reference

Complete REST API reference for the Memory Module. Use these endpoints for direct integration, automation, or when MCP isn’t available.
Prefer MCP? Most users should use MCP Integration for seamless AI assistant integration. Use this API for custom integrations, automation scripts, or non-MCP tools.

Base URL

https://api.ulpi.io/api/v1/memories

Authentication

All endpoints require Bearer token authentication:
Authorization: Bearer YOUR_API_KEY
X-Tenant-ID: your-repository-id
Get your API key:
  1. Log into app.ulpi.io
  2. Navigate to your repository → Settings → API Keys
  3. Click “Generate New Key”
  4. Store securely (shown only once!)

Endpoints

POST /memories

Store a new memory. Request:
curl -X POST https://api.ulpi.io/api/v1/memories \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Tenant-ID: your-repo-id" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Our API uses JWT bearer token authentication. Tokens expire after 30 days of inactivity.",
    "sector": "semantic",
    "tags": ["api", "authentication", "documentation"],
    "source": "API documentation v2",
    "metadata": {
      "version": "2.0",
      "author": "engineering-team"
    }
  }'
Parameters:
  • content (required, string): The information to store
  • sector (optional, string): episodic | semantic | procedural | emotional | reflective
  • tags (optional, array): List of tags for organization
  • source (optional, string): Where this came from
  • metadata (optional, object): Custom JSON metadata
Response:
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "content": "Our API uses JWT bearer...",
    "sector": "semantic",
    "salience": 1.0,
    "access_count": 0,
    "tags": ["api", "authentication", "documentation"],
    "source": "API documentation v2",
    "metadata": {
      "version": "2.0",
      "author": "engineering-team"
    },
    "created_at": "2025-01-25T10:30:00Z",
    "last_accessed_at": null
  }
}
Status Codes:
  • 201: Created successfully
  • 400: Invalid request format
  • 401: Unauthorized (bad API key)
  • 422: Validation failed
  • 429: Rate limit exceeded

POST /memories/search

Search memories with hybrid ranking. Request:
curl -X POST https://api.ulpi.io/api/v1/memories/search \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Tenant-ID: your-repo-id" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "API authentication methods",
    "limit": 10,
    "sector": "semantic",
    "min_salience": 0.3,
    "expand_waypoints": true,
    "max_hops": 3
  }'
Parameters:
  • query (required, string): Search text
  • limit (optional, int): Results to return (default: 10, max: 100)
  • sector (optional, string): Filter by cognitive sector
  • tags (optional, array): Filter by tags
  • min_salience (optional, float): Minimum salience threshold (0.0-1.0)
  • expand_waypoints (optional, bool): Enable context expansion (default: true)
  • max_hops (optional, int): Waypoint traversal depth (default: 3, max: 5)
Response:
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "content": "Our API uses JWT bearer...",
      "sector": "semantic",
      "salience": 0.95,
      "score": 0.92,
      "access_count": 15,
      "tags": ["api", "authentication"],
      "created_at": "2025-01-15T10:00:00Z",
      "last_accessed_at": "2025-01-24T15:30:00Z"
    }
  ],
  "meta": {
    "total": 42,
    "search_time_ms": 145,
    "waypoints_expanded": true
  }
}
Status Codes:
  • 200: Success
  • 400: Invalid request
  • 401: Unauthorized

GET /memories/

Retrieve specific memory by ID. Request:
curl https://api.ulpi.io/api/v1/memories/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Tenant-ID: your-repo-id"
Response:
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "content": "Our API uses JWT bearer...",
    "sector": "semantic",
    "salience": 0.95,
    "access_count": 15,
    "tags": ["api", "authentication"],
    "source": "API documentation",
    "metadata": {},
    "created_at": "2025-01-15T10:00:00Z",
    "last_accessed_at": "2025-01-24T15:30:00Z",
    "embedding_status": "completed"
  }
}
Status Codes:
  • 200: Success
  • 404: Memory not found
  • 401: Unauthorized
Note: Accessing a memory increments access_count and updates last_accessed_at.

PATCH /memories/

Update memory content or metadata. Request:
curl -X PATCH https://api.ulpi.io/api/v1/memories/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Tenant-ID: your-repo-id" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Updated: Our API uses JWT bearer token authentication. Tokens now expire after 60 days.",
    "tags": ["api", "authentication", "updated"],
    "metadata": {
      "last_updated_by": "admin",
      "version": "2.1"
    }
  }'
Parameters:
  • content (optional, string): Update the content
  • tags (optional, array): Replace tags
  • source (optional, string): Update source
  • metadata (optional, object): Replace metadata
Response:
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "content": "Updated: Our API uses...",
    "tags": ["api", "authentication", "updated"],
    "updated_at": "2025-01-25T16:00:00Z"
  }
}
Status Codes:
  • 200: Updated successfully
  • 404: Memory not found
  • 422: Validation failed
Note: Cannot change sector after creation. Embeddings regenerate automatically.

POST /memories//reinforce

Explicitly boost memory salience. Request:
curl -X POST https://api.ulpi.io/api/v1/memories/550e8400-e29b-41d4-a716-446655440000/reinforce \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Tenant-ID: your-repo-id" \
  -H "Content-Type: application/json" \
  -d '{
    "profile": "maintenance"
  }'
Parameters:
  • profile (optional, string): Reinforcement strength
    • quick_refresh: +0.05
    • maintenance: +0.10 (default)
    • deep_learning: +0.15
    • emergency: +0.25
Response:
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "old_salience": 0.75,
    "new_salience": 0.85,
    "profile_used": "maintenance",
    "boost_applied": 0.10
  }
}
Status Codes:
  • 200: Reinforced successfully
  • 404: Memory not found

GET /memories//waypoints

Get semantic connections for a memory. Request:
curl https://api.ulpi.io/api/v1/memories/550e8400-e29b-41d4-a716-446655440000/waypoints \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Tenant-ID: your-repo-id"
Parameters (query string):
  • limit (optional, int): Number of waypoints (default: 20)
  • min_weight (optional, float): Minimum similarity (default: 0.75)
Response:
{
  "data": [
    {
      "connected_memory_id": "660e8400-e29b-41d4-a716-446655440001",
      "weight": 0.85,
      "connected_memory": {
        "id": "660e8400-e29b-41d4-a716-446655440001",
        "content": "Token refresh endpoint: POST /api/auth/refresh",
        "sector": "semantic",
        "salience": 0.90
      }
    }
  ],
  "meta": {
    "total_waypoints": 5
  }
}

DELETE /memories/

Permanently delete a memory. Request:
curl -X DELETE https://api.ulpi.io/api/v1/memories/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Tenant-ID: your-repo-id"
Response:
{
  "message": "Memory deleted successfully"
}
Status Codes:
  • 204: Deleted successfully
  • 404: Memory not found
Warning: This is permanent and cannot be undone!

POST /memories/prune

Remove low-salience memories in bulk. Request:
curl -X POST https://api.ulpi.io/api/v1/memories/prune \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Tenant-ID: your-repo-id" \
  -H "Content-Type: application/json" \
  -d '{
    "threshold": 0.1,
    "sector": "episodic",
    "dry_run": true
  }'
Parameters:
  • threshold (optional, float): Salience threshold (default: 0.1)
  • sector (optional, string): Only prune specific sector
  • dry_run (optional, bool): Preview without deleting (default: false)
Response:
{
  "data": {
    "memories_pruned": 42,
    "threshold_used": 0.1,
    "sector_filter": "episodic",
    "dry_run": true
  }
}

GET /memories/stats

Get system statistics. Request:
curl https://api.ulpi.io/api/v1/memories/stats \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "X-Tenant-ID: your-repo-id"
Response:
{
  "data": {
    "total_memories": 1523,
    "by_sector": {
      "episodic": 320,
      "semantic": 810,
      "procedural": 245,
      "emotional": 98,
      "reflective": 50
    },
    "avg_salience": 0.67,
    "hot_memories": 45,
    "total_waypoints": 3042,
    "embeddings_today": 127,
    "storage_used_mb": 24.5
  }
}

Rate Limits

PlanRate Limit
Starter60 requests/minute
Pro300 requests/minute
Enterprise1000 requests/minute
Headers returned:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1643097600
429 Response:
{
  "message": "Rate limit exceeded",
  "retry_after": 30
}

Error Responses

All errors return consistent JSON format:
{
  "message": "Validation failed",
  "errors": {
    "content": ["The content field is required."],
    "sector": ["Invalid sector. Must be one of: episodic, semantic, procedural, emotional, reflective"]
  }
}
Status Codes:
  • 400: Bad Request (malformed JSON, invalid parameters)
  • 401: Unauthorized (missing/invalid API key)
  • 403: Forbidden (valid auth but no access)
  • 404: Not Found (resource doesn’t exist)
  • 422: Unprocessable Entity (validation failed)
  • 429: Too Many Requests (rate limit exceeded)
  • 500: Internal Server Error

Pagination

For endpoints returning lists, use cursor-based pagination: Request:
curl https://api.ulpi.io/api/v1/memories?limit=20&cursor=eyJpZCI6MTIzfQ \
  -H "Authorization: Bearer YOUR_API_KEY"
Response:
{
  "data": [...],
  "meta": {
    "next_cursor": "eyJpZCI6MTQzfQ",
    "prev_cursor": "eyJpZCI6MTAzfQ",
    "has_more": true
  }
}

Webhooks

Coming soon! Subscribe to memory events:
  • memory.created
  • memory.accessed
  • memory.pruned
  • waypoint.created

SDKs

Official SDKs available:

JavaScript / Node.js

npm install @ulpi/memory-sdk

Python

pip install ulpi-memory

Go

go get github.com/ulpi-io/memory-go
Community SDKs: PHP, Ruby, Rust (see GitHub)

Code Examples

JavaScript / Node.js

const { MemoryClient } = require('@ulpi/memory-sdk');

const client = new MemoryClient({
  apiKey: process.env.ULPI_API_KEY,
  tenantId: process.env.ULPI_TENANT_ID
});

// Store a memory
const memory = await client.memories.create({
  content: "Our API uses JWT authentication...",
  sector: "semantic",
  tags: ["api", "auth"]
});

// Search memories
const results = await client.memories.search({
  query: "authentication methods",
  limit: 10,
  expandWaypoints: true
});

// Reinforce a memory
await client.memories.reinforce(memory.id, {
  profile: "maintenance"
});

Python

from ulpi_memory import MemoryClient

client = MemoryClient(
    api_key=os.environ["ULPI_API_KEY"],
    tenant_id=os.environ["ULPI_TENANT_ID"]
)

# Store a memory
memory = client.memories.create(
    content="Our API uses JWT authentication...",
    sector="semantic",
    tags=["api", "auth"]
)

# Search memories
results = client.memories.search(
    query="authentication methods",
    limit=10,
    expand_waypoints=True
)

# Reinforce a memory
client.memories.reinforce(
    memory.id,
    profile="maintenance"
)

cURL

# Store
curl -X POST https://api.ulpi.io/api/v1/memories \
  -H "Authorization: Bearer $ULPI_API_KEY" \
  -H "X-Tenant-ID: $ULPI_TENANT_ID" \
  -H "Content-Type: application/json" \
  -d '{"content":"Our API uses JWT...","sector":"semantic"}'

# Search
curl -X POST https://api.ulpi.io/api/v1/memories/search \
  -H "Authorization: Bearer $ULPI_API_KEY" \
  -H "X-Tenant-ID: $ULPI_TENANT_ID" \
  -H "Content-Type: application/json" \
  -d '{"query":"authentication","limit":10}'

# Reinforce
curl -X POST https://api.ulpi.io/api/v1/memories/MEMORY_ID/reinforce \
  -H "Authorization: Bearer $ULPI_API_KEY" \
  -H "X-Tenant-ID: $ULPI_TENANT_ID" \
  -H "Content-Type: application/json" \
  -d '{"profile":"maintenance"}'

Best Practices

When storing multiple memories, use async/parallel requests to improve throughput. Don’t wait for each to complete sequentially.
Always implement retry logic with exponential backoff for 5xx errors and rate limits (429).
  • Never commit keys to version control
  • Use environment variables
  • Rotate keys quarterly
  • Use separate keys per environment
  • Cache search results when possible
  • Implement client-side rate limiting
  • Monitor X-RateLimit-Remaining header
  • Upgrade plan if consistently hitting limits

Support

API Issues: Response Times:
  • Starter: 48 hours
  • Pro: 24 hours (priority)
  • Enterprise: 4 hours (dedicated)

Next Steps