API Reference
Spellbook API Reference
Section titled “Spellbook API Reference”The Spellbook API provides a comprehensive set of endpoints for interacting with Temporal Bayesian Knowledge Graphs. This reference documentation covers all available endpoints, request/response formats, authentication methods, and the reasoning behind our API design decisions.
API Design Philosophy
Section titled “API Design Philosophy”The Spellbook API was designed with several key principles in mind:
Why RESTful?
Section titled “Why RESTful?”We chose a RESTful architecture for our API because it provides:
- Familiarity: Most developers are already familiar with REST conventions
- Cacheability: Responses can be cached to improve performance
- Statelessness: Each request contains all information needed for processing
- Resource-oriented: Aligns naturally with knowledge graph entities
While GraphQL offers advantages for complex queries, our REST API includes specialized endpoints for graph traversal that provide similar capabilities with better performance characteristics for our specific use case.
Versioning Strategy
Section titled “Versioning Strategy”The /v1 in our base URL reflects our commitment to API stability. We follow semantic versioning principles:
- Patch changes (e.g., 1.0.1): Bug fixes that don’t affect the API
- Minor changes (e.g., 1.1.0): Backward-compatible additions
- Major changes (e.g., 2.0.0): Breaking changes that require a new version path
This approach ensures that your applications won’t break when we make improvements to the API.
Base URL
Section titled “Base URL”All API endpoints are accessible under the base URL:
https://spellbook.magick.ai/api/v1Authentication
Section titled “Authentication”Authentication is required for all API endpoints. Spellbook uses API keys for authentication.
Why API Keys?
Section titled “Why API Keys?”We chose API key authentication for several reasons:
- Simplicity: Easy to implement and use
- Performance: Minimal overhead for each request
- Security: Keys can be rotated and revoked as needed
- Granular control: Different keys can have different permissions
For applications requiring OAuth flows (e.g., user-specific access), we provide OAuth 2.0 support as well, documented in our Advanced Authentication guide.
API Keys
Section titled “API Keys”To authenticate your requests, include your API key in the Authorization header:
Authorization: Bearer YOUR_API_KEYYou can obtain an API key from the Spellbook Dashboard.
Security Best Practices
Section titled “Security Best Practices”When working with API keys:
- Never expose your API key in client-side code
- Use environment variables to store keys in your applications
- Create separate keys for development and production
- Rotate keys periodically for enhanced security
Core Concepts
Section titled “Core Concepts”Before diving into specific endpoints, it’s important to understand the core concepts of our API:
Memories vs. Entities vs. Relationships
Section titled “Memories vs. Entities vs. Relationships”Our API distinguishes between three fundamental types of resources:
- Memories: Unstructured or semi-structured information with temporal context
- Entities: Distinct objects or concepts with properties
- Relationships: Connections between entities with their own properties
This separation allows for flexible knowledge representation while maintaining a clean API structure.
Confidence Scores
Section titled “Confidence Scores”Almost every resource in Spellbook includes a confidence score (0-1), representing:
- How certain we are about the information
- The reliability of the source
- The consistency with existing knowledge
Understanding and utilizing these confidence scores is crucial for building robust applications.
Endpoints
Section titled “Endpoints”Memory Management
Section titled “Memory Management”Memories are the foundation of temporal knowledge in Spellbook. They represent observations or pieces of information that have a specific temporal context.
Why Memories Matter
Section titled “Why Memories Matter”Traditional knowledge graphs struggle with temporal information and unstructured content. Our memory system addresses this by:
- Capturing temporal context explicitly
- Allowing for natural language content
- Supporting automatic entity and relationship extraction
- Maintaining provenance information
Create Memory
Section titled “Create Memory”POST /memoriesCreates a new memory in the knowledge graph.
Request Body:
{ "content": "Alice met Bob at the conference", "confidence": 0.85, "timestamp": "2025-05-01T14:30:00Z", "metadata": { "source": "user_input", "tags": ["meeting", "conference"] }}Field Explanations:
content: The actual information being stored (required)confidence: How certain we are about this information (0-1, default: 1.0)timestamp: When this information was true/observed (default: current time)metadata: Additional context about the memorysource: Where this information came fromtags: Categorization for easier retrieval
Response:
{ "id": "mem_1a2b3c4d5e6f", "content": "Alice met Bob at the conference", "confidence": 0.85, "timestamp": "2025-05-01T14:30:00Z", "created_at": "2025-05-01T14:32:15Z", "metadata": { "source": "user_input", "tags": ["meeting", "conference"] }}Implementation Notes:
When you create a memory, several processes happen behind the scenes:
- Entity extraction: The system identifies potential entities (e.g., “Alice”, “Bob”, “conference”)
- Relationship inference: Relationships between entities are inferred (e.g., “Alice” → “met” → “Bob”)
- Temporal indexing: The memory is indexed by its timestamp for efficient temporal queries
- Confidence propagation: The memory’s confidence affects derived entities and relationships
Retrieve Memory
Section titled “Retrieve Memory”GET /memories/{memory_id}Retrieves a specific memory by ID.
Why IDs Matter:
We use opaque, prefixed IDs (e.g., mem_1a2b3c4d5e6f) for several reasons:
- Type safety: The prefix indicates the resource type
- Security: IDs don’t expose implementation details
- Flexibility: We can change the underlying ID generation without breaking the API
Response:
{ "id": "mem_1a2b3c4d5e6f", "content": "Alice met Bob at the conference", "confidence": 0.85, "timestamp": "2025-05-01T14:30:00Z", "created_at": "2025-05-01T14:32:15Z", "metadata": { "source": "user_input", "tags": ["meeting", "conference"] }}List Memories
Section titled “List Memories”GET /memoriesLists all memories, with optional filtering.
Query Parameters:
limit(integer): Maximum number of memories to return (default: 20, max: 100)offset(integer): Number of memories to skip (default: 0)start_time(ISO datetime): Filter memories from this timeend_time(ISO datetime): Filter memories until this timetags(comma-separated): Filter by tagsmin_confidence(float): Minimum confidence score (0-1)
Pagination Design:
We use offset-based pagination for simplicity and compatibility with most client libraries. For high-volume applications, we also support cursor-based pagination via the cursor parameter (see Advanced Querying guide).
Response:
{ "memories": [ { "id": "mem_1a2b3c4d5e6f", "content": "Alice met Bob at the conference", "confidence": 0.85, "timestamp": "2025-05-01T14:30:00Z", "created_at": "2025-05-01T14:32:15Z", "metadata": { "source": "user_input", "tags": ["meeting", "conference"] } }, // More memories... ], "total": 42, "limit": 20, "offset": 0}Performance Considerations:
When querying memories, consider:
- Time ranges: Narrowing the time range significantly improves performance
- Confidence filtering: Using
min_confidencecan reduce result size - Tag filtering: Tags are indexed for fast retrieval
Entity Management
Section titled “Entity Management”Entities represent distinct objects, people, concepts, or things in your knowledge graph. They form the nodes in the graph structure.
Why Explicit Entities?
Section titled “Why Explicit Entities?”While memories can contain implicit entities, explicit entity management provides:
- Deduplication: Consolidate information about the same entity
- Property management: Attach and update properties directly
- Type hierarchies: Organize entities into types and subtypes
- Reference stability: Entities persist even as memories change
Create Entity
Section titled “Create Entity”POST /entitiesCreates a new entity in the knowledge graph.
Request Body:
{ "name": "Alice Smith", "type": "person", "properties": { "age": 32, "occupation": "Software Engineer" }, "confidence": 0.95, "metadata": { "source": "user_input" }}Field Explanations:
name: Human-readable identifier for the entity (required)type: Category or class of the entity (required)properties: Key-value pairs describing the entityconfidence: Overall confidence in this entity’s existence (0-1)metadata: Additional context about the entity
Response:
{ "id": "ent_2b3c4d5e6f7g", "name": "Alice Smith", "type": "person", "properties": { "age": 32, "occupation": "Software Engineer" }, "confidence": 0.95, "created_at": "2025-05-01T14:35:22Z", "metadata": { "source": "user_input" }}Implementation Notes:
When creating entities:
- Property validation: Properties are validated against type schemas (if defined)
- Entity resolution: The system checks for potential duplicates
- Temporal tracking: Property changes are tracked over time
- Inference triggers: New entities may trigger inference rules
Relationship Management
Section titled “Relationship Management”Relationships connect entities and form the edges in your knowledge graph. They can have their own properties and temporal context.
Create Relationship
Section titled “Create Relationship”POST /relationshipsCreates a new relationship between entities.
Request Body:
{ "source_id": "ent_2b3c4d5e6f7g", "target_id": "ent_3c4d5e6f7g8h", "type": "knows", "properties": { "since": "2020-01-15", "context": "Work" }, "confidence": 0.85, "timestamp": "2025-05-01T14:30:00Z", "metadata": { "source": "user_input" }}Response:
{ "id": "rel_4d5e6f7g8h9i", "source_id": "ent_2b3c4d5e6f7g", "target_id": "ent_3c4d5e6f7g8h", "type": "knows", "properties": { "since": "2020-01-15", "context": "Work" }, "confidence": 0.85, "timestamp": "2025-05-01T14:30:00Z", "created_at": "2025-05-01T14:36:45Z", "metadata": { "source": "user_input" }}Advanced Querying
Section titled “Advanced Querying”Graph Traversal (a.k.a. GraphRAG)
Section titled “Graph Traversal (a.k.a. GraphRAG)”OH MY NEPTUNE! Graph traversal is the MOST AMAZING feature of Spellbook! It lets you hop-hop-hop through your knowledge graph like a jellyfish dancing through Jellyfish Fields!
POST /query/traverseRequest Body (The Secret Formula):
{ "start_entity_id": "ent_2b3c4d5e6f7g", "pattern": [ { "relationship": "works_at", "direction": "outgoing" }, { "relationship": "located_in", "direction": "outgoing" } ], "max_depth": 2, "min_confidence": 0.7, "time_point": "2025-05-01T00:00:00Z"}This query is like following a TREASURE MAP! It finds where a person works and then where that workplace is located, as of May 1, 2025. It’s like connecting the dots, except the dots are KNOWLEDGE and the lines are RELATIONSHIPS! Isn’t that just coral-tastic?
Natural Language Queries
Section titled “Natural Language Queries”For those times when JSON patterns make your brain feel like BARNACLES, you can use natural language instead! It’s as easy as talking to Gary!
POST /query/naturalRequest Body (Just Ask a Question!):
{ "query": "Where did Alice work in 2024?", "context_entity_ids": ["ent_2b3c4d5e6f7g"], "min_confidence": 0.6}Behind the scenes, we translate your question into a fancy graph pattern. It’s like MAGIC, except it’s actually advanced natural language processing! But you don’t need to worry about that - just ask your question and let us do the heavy lifting. That’s what friends are for!
Error Handling
Section titled “Error Handling”The API uses standard HTTP status codes to indicate the success or failure of requests.
| Status Code | Description | When You’ll See It |
|---|---|---|
| 200 | OK - The request was successful | After successful GET, PUT, PATCH operations |
| 201 | Created - A new resource was created | After successful POST operations that create resources |
| 400 | Bad Request - The request was invalid | When request validation fails (e.g., invalid JSON, missing required fields) |
| 401 | Unauthorized - Authentication failed | When API key is missing or invalid |
| 403 | Forbidden - You don’t have permission | When API key doesn’t have permission for the requested operation |
| 404 | Not Found - The resource was not found | When requesting a non-existent resource by ID |
| 429 | Too Many Requests - Rate limit exceeded | When you’ve exceeded your rate limits |
| 500 | Internal Server Error - Something went wrong | When an unexpected error occurs on our servers |
Why Detailed Error Messages Matter
Section titled “Why Detailed Error Messages Matter”We provide detailed error messages because:
- Developer experience: Clear errors speed up debugging
- Self-service: Most issues can be resolved without contacting support
- Education: Error messages help you learn the API
Error responses include a JSON body with details:
{ "error": { "code": "invalid_request", "message": "The request was invalid", "details": "The 'confidence' field must be a number between 0 and 1", "help_url": "https://docs.spellbook.magick.ai/errors/invalid_request" }}Rate Limiting
Section titled “Rate Limiting”API requests are subject to rate limiting to ensure fair usage and system stability.
Why Rate Limits Exist
Section titled “Why Rate Limits Exist”Rate limits serve several important purposes:
- System stability: Prevent any single client from overwhelming the system
- Fair usage: Ensure resources are available to all users
- Abuse prevention: Mitigate potential denial-of-service attacks
- Cost control: Help you manage your API usage
The current limits are:
- 100 requests per minute per API key
- 5,000 requests per day per API key
Higher limits are available on enterprise plans.
Rate Limit Headers
Section titled “Rate Limit Headers”Rate limit information is included in the response headers:
X-RateLimit-Limit: 100X-RateLimit-Remaining: 95X-RateLimit-Reset: 1620000000Best Practices for Rate Limits
Section titled “Best Practices for Rate Limits”To work effectively within rate limits:
- Implement backoff: When you receive a 429, wait before retrying
- Batch operations: Use bulk endpoints where available
- Cache responses: Store results that don’t change frequently
- Monitor usage: Track your usage against your limits
SDKs and Client Libraries
Section titled “SDKs and Client Libraries”Spellbook provides official client libraries for several programming languages:
Why Use Our SDKs?
Section titled “Why Use Our SDKs?”Our official SDKs provide several advantages:
- Type safety: Properly typed interfaces for your language
- Error handling: Consistent error handling patterns
- Authentication: Built-in API key management
- Rate limiting: Automatic retry with exponential backoff
- Pagination: Helpers for working with paginated results
Webhooks
Section titled “Webhooks”Spellbook can send webhook notifications when certain events occur in your knowledge graph.
Why Webhooks?
Section titled “Why Webhooks?”Webhooks enable real-time integration by:
- Eliminating polling: No need to constantly check for changes
- Enabling event-driven architecture: React to changes as they happen
- Reducing latency: Get notified immediately when important events occur
Configure webhooks in the Spellbook Dashboard.
Webhook Security
Section titled “Webhook Security”To ensure webhook security:
- Verify signatures: All webhooks include an HMAC signature
- Use HTTPS: Only HTTPS endpoints are supported
- Implement timeouts: Discard events with old timestamps
Implementation Examples
Section titled “Implementation Examples”Creating a Memory and Querying Related Entities
Section titled “Creating a Memory and Querying Related Entities”This example shows how to create a memory and then query entities extracted from it:
# Using the Python SDKfrom spellbook import Spellbook
client = Spellbook(api_key="your_api_key")
# Create a memorymemory = client.memories.create( content="Alice started working at Acme Corp in January 2025", confidence=0.9, timestamp="2025-01-15T09:00:00Z")
# Wait for processing (in production, use webhooks instead)import timetime.sleep(2)
# Query entities related to this memoryentities = client.memories.get_related_entities(memory.id)
# Print the extracted entitiesfor entity in entities: print(f"{entity.name} ({entity.type}): {entity.confidence}")Performance Optimization
Section titled “Performance Optimization”Batch Operations
Section titled “Batch Operations”For high-throughput applications, use batch endpoints:
POST /memories/batch{ "memories": [ { "content": "Alice met Bob at the conference", "confidence": 0.85, "timestamp": "2025-05-01T14:30:00Z" }, { "content": "Bob works at Acme Corp", "confidence": 0.9, "timestamp": "2025-05-01T14:35:00Z" } ]}Caching Strategies
Section titled “Caching Strategies”Implement effective caching by:
- Respecting Cache-Control headers: We set appropriate caching directives
- Using ETags: Check if resources have changed before fetching again
- Caching immutable resources: Historical data doesn’t change