API and OpenAPI specification
The Neotoma REST API is defined in the OpenAPI spec. The table below lists each endpoint and the capability it provides.
The API is designed around deterministic state operations: store structured observations, retrieve snapshots with provenance, and manage typed relationships explicitly.
Base URL
- Development:
http://localhost:3080 - Production:
http://localhost:3180(local) or your deployed host
Authentication
Most write endpoints require authentication. Discovery routes like /health, /server-info, and /.well-known/* are unauthenticated. When authentication is enabled, include a Bearer token:
Authorization: Bearer <NEOTOMA_BEARER_TOKEN>
- Set via
NEOTOMA_BEARER_TOKENenvironment variable - When encryption is enabled, use the key-derived MCP token instead:
neotoma auth mcp-token - MCP OAuth endpoints (
/mcp/oauth/*) have their own auth flow - see the MCP reference - For agent identity (cryptographically verifiable writes via RFC 9421 signatures and the
aa-agent+jwttoken), see the AAuth reference. Bearer auth and AAuth are independent and stack: Bearer authorizes the connection, AAuth attributes individual writes.
Request examples
# Store structured entities
curl -X POST http://localhost:3080/store \
-H "Authorization: Bearer $NEOTOMA_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"entities":[{"entity_type":"task","title":"Review schema changes","status":"open"}]}'
# Query entities
curl -X POST http://localhost:3080/entities/query \
-H "Authorization: Bearer $NEOTOMA_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"filters":{"entity_type":"task"},"limit":10}'
# Retrieve snapshot with provenance
curl -X POST http://localhost:3080/get_entity_snapshot \
-H "Authorization: Bearer $NEOTOMA_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"entity_id":"<entity_id>"}'
# Store a file with entities (unified store)
curl -X POST http://localhost:3080/store \
-H "Authorization: Bearer $NEOTOMA_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"entities":[{"entity_type":"note","title":"Meeting notes"}],"file_path":"/path/to/document.pdf"}'
# Health check (no auth required)
curl http://localhost:3080/healthError responses
All errors use a structured envelope:
{
"error_code": "INGESTION_FILE_TOO_LARGE",
"message": "File exceeds maximum size of 50MB",
"details": { "file_size": 52428800, "max_size": 52428800 },
"trace_id": "trace-uuid",
"timestamp": "2024-01-01T12:00:00Z"
}Standard HTTP status codes: 200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 409 Conflict, 413 Payload Too Large, 429 Rate Limited, 500 Internal Server Error, 503 Service Unavailable. Check error_code for programmatic handling, not just the HTTP status.
Pagination
List endpoints accept limit and offset parameters. Use include_total_count: true when building pagination UI. Recommended: keep limit at 100 or below for performance.
{
"filters": { "entity_type": "task" },
"limit": 20,
"offset": 0,
"include_total_count": true
}File operations
Upload files via the unified POST /store (with file_path or file_content + mime_type) or POST /store/unstructured for raw file ingestion. File size limit: 50 MB. Retrieve signed URLs via GET /get_file_url?file_path=... (default expiry: 1 hour).
Continue with MCP reference, CLI reference, schema management, architecture, and expose tunnel.