Authentication
All API requests require authentication using an API key. Get your key from the Meridian Dashboard and store it securely as an environment variable.
Environment Variable (Recommended)
export MERIDIAN_API_KEY="kt_your_api_key_here"import os
from meridian_sdk import MeridianAPI
# Load from environment
api_key = os.getenv("MERIDIAN_API_KEY")
# Initialize client
async with MeridianAPI(api_key=api_key) as client:
# Make authenticated requests
response = await client.search("your query")Note: API keys start with kt_ and should never be committed to version control.
Configuration
Customize client behavior with configuration options.
Client Options
api_keystring (required)Your Meridian API key
base_urlstring (optional)API base URL - defaults to production endpoint
timeoutfloat (optional)Request timeout in seconds - default: 60.0
max_retriesint (optional)Maximum retry attempts - default: 3
client = MeridianAPI(
api_key="kt_...",
base_url="https://dashboard.trymeridian.dev",
timeout=60.0,
max_retries=3
)search()
Search across all your connected data sources with natural language queries. Returns ranked results with relevance scores, snippets, and source attribution.
Parameters
querystring (required)Natural language search query (e.g., "What did we promise to Acme Corp?")
output_formatstring (optional)Output format: "json" | "csv" | "strings" | "markdown" - default: "json"
filtersSearchFilters (optional)Filter results by source, file type, date range, or entities
optionsSearchOptions (optional)Search configuration (max results, entity filtering, etc.)
Returns
SearchResponseObject containing results, metadata, and source information
results - List of search results with title, snippet, relevance scoresources_count - Number of data sources searchedtotal_results - Total number of matches foundfrom meridian_sdk import MeridianAPI, SearchFilters, SearchOptions
async with MeridianAPI(api_key=api_key) as client:
# Simple search
response = await client.search("project Apollo status")
for result in response.results:
print(f"Title: {result.title}")
print(f"Snippet: {result.snippet}")
print(f"Relevance: {result.relevance_score:.2%}")
print(f"Source: {result.source_type}\n")
# Advanced search with filters
filters = SearchFilters(
sources=["google_drive", "sharepoint"],
file_types=["PDF", "DOCUMENT"],
date_range=(30, 0), # Past 30 days
entities=["Stellar Dynamics", "Q4"]
)
options = SearchOptions(
max_results=20,
include_sources=True,
use_entity_filtering=True
)
response = await client.search(
query="Q4 financial reports",
filters=filters,
options=options
)
print(f"Found {len(response.results)} results from {response.sources_count} sources")Output Formats
Get search results in different formats optimized for various use cases.
JSON (default)
Structured data with full metadata
response = await client.search("revenue report", output_format="json")
for result in response.results:
print(f"{result.title} - {result.relevance_score:.2%}")CSV
Export to spreadsheets
csv_data = await client.search("revenue report", output_format="csv")
with open("results.csv", "w") as f:
f.write(csv_data)Strings Array
Simple list of snippets
snippets = await client.search("revenue report", output_format="strings")
for snippet in snippets:
print(snippet)Markdown
Formatted with citations
markdown = await client.search("revenue report", output_format="markdown")
print(markdown) # Formatted text with [1], [2] citationssearch_summaries()
Search pre-generated daily summaries for emails, messages, or document changes.
# Get email summaries about a specific topic
response = await client.search_summaries(
query="Deloitte project communications",
summary_type="EMAIL_SUMMARIES",
date_range=(7, 0), # Past week
use_semantic_search=True
)
for summary in response.summaries:
print(f"📧 {summary.generated_at}")
print(f" {summary.summary_text}")
print(f" References {len(summary.referenced_ids)} emails\n")get_context()
Retrieve the full document text after finding relevant chunks.
# First search for relevant documents
search_response = await client.search("API documentation")
# Get full context for the first result
if search_response.results:
content_id = search_response.results[0].content_id
context = await client.get_context(content_id, max_chars=50000)
print(f"Title: {context.title}")
print(f"Size: {context.size_chars:,} characters")
print(f"\n{context.full_text}")get_usage()
Monitor API usage and costs with detailed analytics.
Parameters
periodstring (optional)"day" | "week" | "month" - default: "month"
start_datestring (optional)Custom start date (YYYY-MM-DD)
end_datestring (optional)Custom end date (YYYY-MM-DD)
# Get monthly usage
usage = await client.get_usage(period="month")
print(f"Total requests: {usage.total_requests}")
print(f"Total cost: ${usage.total_cost:.4f}")
print(f"Current tier: {usage.current_tier}")
# Daily breakdown
for day in usage.daily_breakdown:
print(f"{day.date}: {day.requests} requests, ${day.cost:.4f}")get_limits()
Check your current rate limits and remaining quota.
Returns
RateLimitInfoObject containing rate limit information
requests_per_day - Total daily request limitrequests_per_minute - Per-minute rate limitremaining_day - Remaining requests todayremaining_minute - Remaining requests this minute# Check rate limits
limits = await client.get_limits()
print(f"Daily limit: {limits.remaining_day}/{limits.requests_per_day}")
print(f"Per minute: {limits.remaining_minute}/{limits.requests_per_minute}")
# Check before making requests
if limits.remaining_minute > 0:
response = await client.search("query")
else:
print("Rate limit reached, waiting...")list_sources()
List all connected data sources and their status.
sources = await client.list_sources()
print(f"Connected sources: {sources.total_connected}")
for source in sources.sources:
status = "✅" if source.is_connected else "❌"
print(f"{status} {source.name} ({source.type})")health_check()
Check API status and service health.
health = await client.health_check()
print(f"API Status: {health.status}")
print(f"Version: {health.version}")
for service_name, service in health.services.items():
print(f" {service_name}: {service.status}")Error Handling
Handle API errors with specific exception types.
from meridian_sdk import (
MeridianAPI,
AuthenticationError,
RateLimitError,
ValidationError,
ServerError
)
async with MeridianAPI(api_key=api_key) as client:
try:
response = await client.search("test query")
except AuthenticationError:
print("Invalid API key")
except RateLimitError as e:
print(f"Rate limit exceeded. Retry after {e.retry_after}s")
except ValidationError as e:
print(f"Validation error: {e.message}")
except ServerError as e:
print(f"Server error: {e.status_code}")Context Manager
The SDK supports both context manager pattern (recommended) and manual session management.
Context Manager (Recommended)
Automatically handles connection cleanup
# Recommended: Use context manager for automatic cleanup
async with MeridianAPI(api_key=api_key) as client:
response = await client.search("query")
# Connection automatically closed when exiting contextManual Management
Explicit control over connection lifecycle
# Manual management (if needed)
client = MeridianAPI(api_key=api_key)
await client.__aenter__()
try:
response = await client.search("query")
finally:
await client.__aexit__(None, None, None)Advanced Examples
Complex patterns for production applications.
Batch Processing
Process multiple searches efficiently with async
import asyncio
queries = [
"Q4 sales report",
"Employee handbook",
"Product roadmap"
]
async with MeridianAPI(api_key=api_key) as client:
# Execute all searches concurrently
tasks = [client.search(query) for query in queries]
responses = await asyncio.gather(*tasks)
# Process results
for query, response in zip(queries, responses):
print(f"Query: {query}")
print(f"Results: {len(response.results)}\n")Graceful Error Recovery
Handle failures with retries and fallbacks
from meridian_sdk import RateLimitError
import asyncio
async def search_with_retry(client, query, max_retries=3):
for attempt in range(max_retries):
try:
return await client.search(query)
except RateLimitError as e:
if attempt < max_retries - 1:
wait_time = e.retry_after or (2 ** attempt)
print(f"Rate limited, waiting {wait_time}s...")
await asyncio.sleep(wait_time)
else:
raise
async with MeridianAPI(api_key=api_key) as client:
response = await search_with_retry(client, "important query")Models & Types
SearchFilters
sourceslist[string]Filter by data source names
file_typeslist[string]Filter by file types (PDF, DOCUMENT, etc.)
date_rangetuple[int, int](days_back, days_forward) - Date range tuple
entitieslist[string]Filter by entity names
SearchOptions
max_resultsint (1-100)Maximum number of results to return
include_sourcesboolInclude source documents in response
use_entity_filteringboolEnable AI-powered entity filtering