SDK Documentation
The MATIH Platform provides official SDKs in three languages -- Python, TypeScript, and Java -- to enable programmatic access to platform services. This section covers installation, authentication, core API methods, and usage examples for each SDK.
SDK Overview
| SDK | Language | Location | Primary Use Cases |
|---|---|---|---|
| Python SDK | Python 3.10+ | sdks/python/ | Data engineering, ML workflows, AI agent integration, Jupyter notebooks |
| TypeScript SDK | TypeScript/Node.js 18+ | sdks/typescript/ | Frontend integration, server-side scripting, CI/CD automation |
| Java Inference SDK | Java 17+ | sdks/inference/ | Model serving integration, high-performance batch inference, JVM applications |
All SDKs share common design principles:
- Consistent API surface: Method names and parameters are aligned across languages
- Built-in authentication: JWT token management with automatic refresh
- Tenant-aware: All operations are scoped to a tenant context
- Type-safe: Full type definitions for request/response objects
- Async support: Asynchronous methods for non-blocking operations
- Error handling: Structured error types that map to the platform error code system
- Streaming support: Server-Sent Events and WebSocket clients for real-time AI responses
Python SDK
Installation
# Install from PyPI
pip install matih-sdk
# Install with optional dependencies for ML workflows
pip install matih-sdk[ml]
# Install with all optional dependencies
pip install matih-sdk[all]
# Install from source (development)
cd sdks/python
pip install -e ".[dev]"Requirements
| Requirement | Version |
|---|---|
| Python | 3.10 or later |
| httpx | 0.25+ |
| pydantic | 2.0+ |
| websockets | 12.0+ (for streaming) |
Authentication
from matih_sdk import MatihClient
# Option 1: Username/password authentication
client = MatihClient(
base_url="https://platform.matih.ai",
tenant_slug="acme"
)
client.authenticate(email="user@acme.com", password="********")
# Option 2: API token authentication (for CI/CD and service accounts)
client = MatihClient(
base_url="https://platform.matih.ai",
tenant_slug="acme",
api_token="mtk_a1b2c3d4e5f6g7h8i9j0..."
)
# Option 3: OAuth2 token (from external identity provider)
client = MatihClient(
base_url="https://platform.matih.ai",
tenant_slug="acme",
access_token="eyJhbGciOiJSUzI1NiIs..."
)The client automatically handles token refresh. When the access token expires, the SDK uses the refresh token to obtain a new access token without interrupting the caller.
Configuration Options
from matih_sdk import MatihClient, ClientConfig
config = ClientConfig(
timeout=60, # Request timeout in seconds
max_retries=3, # Maximum retry attempts for failed requests
retry_delay=1.0, # Base delay between retries in seconds
retry_backoff=2.0, # Exponential backoff multiplier
verify_ssl=True, # Verify TLS certificates
log_level="INFO", # SDK logging level
user_agent="my-app/1.0", # Custom User-Agent header
)
client = MatihClient(
base_url="https://platform.matih.ai",
tenant_slug="acme",
config=config
)AI Service - Conversational Analytics
# Synchronous chat
response = client.ai.chat(
message="Show me total revenue by region for Q4 2025",
conversation_id="conv-abc123", # Optional: continue existing conversation
data_source="sales_warehouse",
dialect="trino"
)
print(response.text) # Natural language response
print(response.sql) # Generated SQL
print(response.data.columns) # Column names
print(response.data.rows) # Result rows
print(response.visualization) # Visualization config
# Streaming chat (Server-Sent Events)
async for event in client.ai.chat_stream(
message="Analyze customer churn trends over the past year",
data_source="analytics_db"
):
if event.type == "text":
print(event.data, end="", flush=True)
elif event.type == "sql":
print(f"\nSQL: {event.data}")
elif event.type == "data":
print(f"\nResults: {event.data}")
elif event.type == "visualization":
print(f"\nChart: {event.data}")
elif event.type == "agent_step":
print(f"\n[Agent: {event.data.agent_name}] {event.data.status}")
# WebSocket chat (bidirectional real-time)
async with client.ai.ws_connect() as ws:
await ws.send_message("What are the top 10 products by revenue?")
async for event in ws.events():
if event.type == "complete":
print(event.response.text)
break
elif event.type == "token":
print(event.data, end="", flush=True)AI Service - Text-to-SQL
# Generate SQL from natural language
result = client.ai.text_to_sql(
question="How many active users signed up last month?",
dialect="trino",
catalog="iceberg",
schema="analytics"
)
print(result.sql) # Generated SQL query
print(result.explanation) # Natural language explanation of the SQL
print(result.confidence) # Confidence score (0-1)
print(result.tables_used) # List of tables referenced
# Validate generated SQL
validation = client.ai.validate_sql(
sql=result.sql,
dialect="trino"
)
print(validation.valid) # Boolean
print(validation.errors) # List of validation errors (if any)
print(validation.warnings) # List of optimization suggestions
# Explain existing SQL in natural language
explanation = client.ai.explain_sql(
sql="SELECT region, SUM(amount) FROM orders GROUP BY region HAVING SUM(amount) > 100000"
)
print(explanation.text) # Human-readable explanationAI Service - Feedback
# Submit feedback on a response
client.ai.submit_feedback(
message_id="msg-def456",
rating="positive", # "positive", "negative", "neutral"
comment="SQL was correct and the visualization was helpful",
correction=None # Optional: corrected SQL for negative feedback
)
# Submit feedback with SQL correction
client.ai.submit_feedback(
message_id="msg-ghi789",
rating="negative",
comment="Revenue should use net_amount, not gross_amount",
correction="SELECT region, SUM(net_amount) AS total_revenue FROM sales.orders GROUP BY region"
)Query Engine
# Execute a SQL query
result = client.query.execute(
sql="SELECT region, COUNT(*) as user_count FROM users GROUP BY region",
catalog="iceberg",
schema="analytics",
timeout=120 # Query timeout in seconds
)
print(result.columns) # ['region', 'user_count']
print(result.rows) # [['North America', 1250], ['Europe', 890], ...]
print(result.row_count) # Total number of rows
print(result.duration_ms) # Execution time in milliseconds
# Async query for long-running operations
job = client.query.execute_async(
sql="SELECT * FROM large_table WHERE date > '2025-01-01'",
catalog="iceberg",
schema="warehouse"
)
print(job.job_id) # Job identifier
print(job.status) # QUEUED, RUNNING, COMPLETED, FAILED
# Poll for completion
result = client.query.wait_for_result(job.job_id, timeout=300)
# Or check status manually
status = client.query.get_job_status(job.job_id)
if status.status == "COMPLETED":
result = client.query.get_job_results(job.job_id)Catalog Service
# Browse catalog
databases = client.catalog.list_databases()
tables = client.catalog.list_tables(database="analytics")
table_meta = client.catalog.get_table("analytics", "orders")
print(table_meta.name)
print(table_meta.columns) # List of column definitions
print(table_meta.row_count)
print(table_meta.size_bytes)
print(table_meta.tags)
# Get data lineage
lineage = client.catalog.get_lineage(
table_id=table_meta.id,
direction="both", # "upstream", "downstream", "both"
depth=3
)
# Search metadata
results = client.catalog.search(
query="customer revenue",
entity_types=["table", "column"],
limit=20
)ML Service
# List models
models = client.ml.list_models()
# Register a model
model = client.ml.register_model(
name="churn_predictor",
description="Customer churn prediction model",
tags={"team": "ml-engineering", "use_case": "retention"}
)
# Submit a training job
job = client.ml.submit_training_job(
experiment_name="churn-experiment-v2",
model_name="churn_predictor",
config={
"framework": "pytorch",
"epochs": 100,
"batch_size": 64,
"learning_rate": 0.001,
"dataset": "s3://matih-data/training/churn_dataset.parquet"
},
resources={
"cpu": "4",
"memory": "16Gi",
"gpu": "1"
}
)
# Wait for training completion
result = client.ml.wait_for_training(job.job_id, timeout=3600)
print(result.metrics) # {'accuracy': 0.94, 'f1_score': 0.91, 'auc': 0.96}
# Deploy model for serving
deployment = client.ml.deploy_model(
model_name="churn_predictor",
version="3",
min_replicas=2,
max_replicas=10,
target_cpu_utilization=70
)
# Run inference
prediction = client.ml.predict(
deployment_id=deployment.id,
input_data={
"customer_age": 35,
"tenure_months": 24,
"monthly_spend": 150.0,
"support_tickets": 3
}
)
print(prediction.output) # {'churn_probability': 0.23, 'prediction': 'retain'}
print(prediction.latency_ms) # Inference latencyDashboard and BI Service
# List dashboards
dashboards = client.bi.list_dashboards()
# Create a dashboard
dashboard = client.bi.create_dashboard(
name="Revenue Overview Q4 2025",
description="Executive revenue dashboard",
layout="grid",
widgets=[
{
"type": "kpi",
"title": "Total Revenue",
"query": "SELECT SUM(amount) FROM orders WHERE quarter = 'Q4'",
"position": {"x": 0, "y": 0, "w": 4, "h": 2}
},
{
"type": "bar",
"title": "Revenue by Region",
"query": "SELECT region, SUM(amount) FROM orders GROUP BY region",
"position": {"x": 4, "y": 0, "w": 8, "h": 4}
}
]
)
# Export dashboard
pdf_bytes = client.bi.export_dashboard(
dashboard_id=dashboard.id,
format="pdf",
include_filters=True
)
with open("revenue_q4.pdf", "wb") as f:
f.write(pdf_bytes)Error Handling
from matih_sdk.exceptions import (
MatihAuthenticationError,
MatihPermissionError,
MatihNotFoundError,
MatihValidationError,
MatihRateLimitError,
MatihServerError,
MatihTimeoutError,
MatihConnectionError
)
try:
response = client.ai.chat(message="Show me revenue data")
except MatihAuthenticationError as e:
print(f"Auth failed: {e.code} - {e.message}")
# Re-authenticate or redirect to login
except MatihPermissionError as e:
print(f"Access denied: {e.message}")
except MatihRateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after} seconds")
except MatihValidationError as e:
print(f"Validation error: {e.message}")
for field_error in e.field_errors:
print(f" {field_error.field}: {field_error.message}")
except MatihServerError as e:
print(f"Server error: {e.code} - {e.message}")
print(f"Request ID: {e.request_id}")
print(f"Trace ID: {e.trace_id}")
except MatihTimeoutError as e:
print(f"Request timed out after {e.timeout}s")
except MatihConnectionError as e:
print(f"Connection failed: {e.message}")TypeScript SDK
Installation
# Install from npm
npm install @matih/sdk
# Install with peer dependencies
npm install @matih/sdk @matih/types
# Install from source (development)
cd sdks/typescript
npm install
npm run buildRequirements
| Requirement | Version |
|---|---|
| Node.js | 18.0 or later |
| TypeScript | 5.0+ (if using TypeScript) |
Authentication
import { MatihClient, AuthMethod } from '@matih/sdk';
// Option 1: Username/password
const client = new MatihClient({
baseUrl: 'https://platform.matih.ai',
tenantSlug: 'acme',
});
await client.authenticate({
email: 'user@acme.com',
password: '********',
});
// Option 2: API token
const client = new MatihClient({
baseUrl: 'https://platform.matih.ai',
tenantSlug: 'acme',
apiToken: 'mtk_a1b2c3d4e5f6g7h8i9j0...',
});
// Option 3: Access token (from OAuth2 flow in browser)
const client = new MatihClient({
baseUrl: 'https://platform.matih.ai',
tenantSlug: 'acme',
accessToken: 'eyJhbGciOiJSUzI1NiIs...',
refreshToken: 'eyJhbGciOiJSUzI1NiIs...',
});Configuration
const client = new MatihClient({
baseUrl: 'https://platform.matih.ai',
tenantSlug: 'acme',
apiToken: 'mtk_...',
config: {
timeout: 60000, // Request timeout in ms
maxRetries: 3, // Maximum retry attempts
retryDelay: 1000, // Base retry delay in ms
retryBackoff: 2, // Exponential backoff multiplier
headers: { // Custom headers
'X-Custom-Header': 'value',
},
},
});AI Service - Chat
// Synchronous chat
const response = await client.ai.chat({
message: 'Show me total revenue by region for Q4 2025',
conversationId: 'conv-abc123',
dataSource: 'sales_warehouse',
dialect: 'trino',
});
console.log(response.text);
console.log(response.sql);
console.log(response.data?.columns);
console.log(response.data?.rows);
// Streaming chat (SSE)
const stream = client.ai.chatStream({
message: 'Analyze customer churn trends',
dataSource: 'analytics_db',
});
for await (const event of stream) {
switch (event.type) {
case 'text':
process.stdout.write(event.data);
break;
case 'sql':
console.log(`\nGenerated SQL: ${event.data}`);
break;
case 'data':
console.log(`\nResults: ${JSON.stringify(event.data)}`);
break;
case 'error':
console.error(`Error: ${event.data.message}`);
break;
}
}
// WebSocket chat (React hook example)
import { useMatihChat } from '@matih/sdk/react';
function ChatComponent() {
const { sendMessage, messages, isConnected, isLoading } = useMatihChat({
client,
conversationId: 'conv-abc123',
});
const handleSend = async (text: string) => {
await sendMessage({ message: text });
};
return (
<div>
{messages.map((msg) => (
<div key={msg.id}>{msg.text}</div>
))}
</div>
);
}Query Engine
// Execute query
const result = await client.query.execute({
sql: 'SELECT region, COUNT(*) as count FROM users GROUP BY region',
catalog: 'iceberg',
schema: 'analytics',
});
// Async query
const job = await client.query.executeAsync({
sql: 'SELECT * FROM large_table WHERE date > \'2025-01-01\'',
});
const result = await client.query.waitForResult(job.jobId, {
timeout: 300000,
pollInterval: 2000,
});Error Handling
import {
MatihAuthenticationError,
MatihPermissionError,
MatihNotFoundError,
MatihRateLimitError,
MatihServerError,
} from '@matih/sdk';
try {
const response = await client.ai.chat({ message: 'Show revenue' });
} catch (error) {
if (error instanceof MatihAuthenticationError) {
console.error(`Auth failed: ${error.code}`);
// Redirect to login
} else if (error instanceof MatihRateLimitError) {
console.error(`Rate limited. Retry after ${error.retryAfter}s`);
// Retry with delay
} else if (error instanceof MatihServerError) {
console.error(`Server error: ${error.code} - ${error.message}`);
console.error(`Request ID: ${error.requestId}`);
}
}Java Inference SDK
Installation
Maven:
<dependency>
<groupId>ai.matih</groupId>
<artifactId>matih-inference-sdk</artifactId>
<version>1.0.0</version>
</dependency>Gradle:
implementation 'ai.matih:matih-inference-sdk:1.0.0'Requirements
| Requirement | Version |
|---|---|
| Java | 17 or later |
| Jackson | 2.15+ (transitive dependency) |
| OkHttp | 4.12+ (transitive dependency) |
Authentication
import ai.matih.sdk.MatihClient;
import ai.matih.sdk.auth.ApiTokenAuth;
import ai.matih.sdk.auth.JwtAuth;
// API token authentication
MatihClient client = MatihClient.builder()
.baseUrl("https://platform.matih.ai")
.tenantSlug("acme")
.auth(new ApiTokenAuth("mtk_a1b2c3d4e5f6g7h8i9j0..."))
.build();
// JWT authentication
MatihClient client = MatihClient.builder()
.baseUrl("https://platform.matih.ai")
.tenantSlug("acme")
.auth(new JwtAuth("user@acme.com", "********"))
.build();Model Inference
import ai.matih.sdk.inference.*;
// Single prediction
PredictionRequest request = PredictionRequest.builder()
.deploymentId("dep-abc123")
.input(Map.of(
"customer_age", 35,
"tenure_months", 24,
"monthly_spend", 150.0,
"support_tickets", 3
))
.build();
PredictionResponse response = client.inference().predict(request);
System.out.println("Prediction: " + response.getOutput());
System.out.println("Latency: " + response.getLatencyMs() + "ms");
// Batch prediction
BatchPredictionRequest batchRequest = BatchPredictionRequest.builder()
.deploymentId("dep-abc123")
.inputs(List.of(
Map.of("customer_age", 35, "tenure_months", 24),
Map.of("customer_age", 45, "tenure_months", 12),
Map.of("customer_age", 28, "tenure_months", 36)
))
.build();
BatchPredictionResponse batchResponse = client.inference().predictBatch(batchRequest);
for (PredictionResult result : batchResponse.getResults()) {
System.out.println(result.getOutput());
}Query Execution
import ai.matih.sdk.query.*;
QueryResult result = client.query().execute(
QueryRequest.builder()
.sql("SELECT region, SUM(revenue) FROM sales GROUP BY region")
.catalog("iceberg")
.schema("analytics")
.timeout(Duration.ofSeconds(120))
.build()
);
System.out.println("Columns: " + result.getColumns());
for (List<Object> row : result.getRows()) {
System.out.println(row);
}Error Handling
import ai.matih.sdk.exceptions.*;
try {
PredictionResponse response = client.inference().predict(request);
} catch (MatihAuthenticationException e) {
System.err.println("Authentication failed: " + e.getCode());
} catch (MatihRateLimitException e) {
System.err.println("Rate limited. Retry after " + e.getRetryAfter() + "s");
Thread.sleep(e.getRetryAfter() * 1000L);
} catch (MatihServerException e) {
System.err.println("Server error: " + e.getCode() + " - " + e.getMessage());
System.err.println("Request ID: " + e.getRequestId());
} catch (MatihException e) {
System.err.println("SDK error: " + e.getMessage());
}SDK Comparison Matrix
| Feature | Python SDK | TypeScript SDK | Java Inference SDK |
|---|---|---|---|
| Chat (synchronous) | Yes | Yes | No |
| Chat (streaming SSE) | Yes | Yes | No |
| Chat (WebSocket) | Yes | Yes | No |
| Text-to-SQL | Yes | Yes | No |
| Query execution | Yes | Yes | Yes |
| Async queries | Yes | Yes | Yes |
| Catalog browsing | Yes | Yes | No |
| ML model management | Yes | Yes | No |
| Model inference | Yes | Yes | Yes |
| Batch inference | Yes | Yes | Yes |
| Dashboard management | Yes | Yes | No |
| Feedback submission | Yes | Yes | No |
| React hooks | No | Yes | No |
| Auto token refresh | Yes | Yes | Yes |
| Retry with backoff | Yes | Yes | Yes |
| Structured errors | Yes | Yes | Yes |
| OpenTelemetry tracing | Yes | Yes | Yes |