# Sparkient > Sub-100ms Decision Intelligence API — smarter than rules, cheaper than LLMs. Sparkient is a decision intelligence API that delivers structured decisions in under 100 milliseconds. It compiles LLM intelligence into fast ONNX models at training time, so you get near-LLM quality at near-zero runtime cost. - Base URL: `https://api.sparkient.ai` - OpenAPI Spec: `https://docs.sparkient.ai/openapi.json` - Auth: Bearer token (API key or Firebase JWT) --- # Welcome to Sparkient Sub-100ms Decision Intelligence API — smarter than rules, cheaper than LLMs. ## What is Sparkient? Sparkient is a **decision intelligence API** that delivers structured decisions in under 100 milliseconds. It sits between hard-coded rules and full LLM calls, giving you the reasoning quality of a large language model at the speed and cost of a rules engine. ### The Decision Pipeline Every decision flows through a three-stage pipeline: 1. **Hard Rules (CEL)** — Deterministic business rules evaluated in sub-millisecond time. If a rule matches, the decision is instant. 2. **ML Classifier (ONNX)** — A compiled model trained from LLM-generated examples. Handles nuance and edge cases that rules miss, in under 100ms. 3. **LLM Escalation (Gemini)** — Fallback for low-confidence decisions. Only triggered when the classifier isn't sure enough. Every response is structured and consistent: ```json { "decision": "approve", "confidence": 0.94, "reason_codes": ["safe_content", "verified_user"], "latency_ms": 8.3, "stage": "classifier", "escalate": false } ``` ### Why Not Just Use an LLM? | Approach | Latency | Cost per Decision | Intelligence | |:---------|:-------:|:-----------------:|:------------:| | Rules Engine | < 1ms | ~$0 | Low | | **Sparkient** | **< 100ms** | **~$0** | **Near-LLM** | | Fast LLM (Groq) | 150–300ms | $0.001–0.005 | High | | Standard LLM | 1–3s | $0.001–0.01 | Highest | Sparkient compiles LLM intelligence into a fast model at training time, so you get near-LLM quality at near-zero runtime cost. ## Programmatic Access Building an integration or using an AI agent? These machine-readable resources are available: - API Base URL: https://api.sparkient.ai - OpenAPI Spec: https://api.sparkient.ai/openapi.json — full API schema - Plain text docs: https://docs.sparkient.ai/llms-full.txt — complete documentation in markdown - LLM summary: https://docs.sparkient.ai/llms.txt — concise overview for AI agents ## Next Steps - [Quickstart](https://docs.sparkient.ai/docs/quickstart/): Get your API key and make your first decision in 5 minutes. - [Authentication](https://docs.sparkient.ai/docs/authentication/): Learn about API keys and Firebase JWT authentication. - [Core Concepts](https://docs.sparkient.ai/docs/concepts/decision-types/): Understand decision types, rules, training, and the pipeline. - [API Reference](https://docs.sparkient.ai/docs/api-reference/): Full interactive API reference generated from the OpenAPI spec. --- # Quickstart Get your API key and make your first decision in 5 minutes. ## 1. Get Your API Key Sign in to the [Sparkient Dashboard](https://app.sparkient.ai) and navigate to **Settings → API Keys**. Click **Create API Key**, give it a name, and copy the key. > **Warning:** Your API key is shown only once. Copy it and store it securely. ## 2. Create a Decision Type A **decision type** defines what you're deciding. It specifies the possible outcomes, reason codes, and any hard rules. ```bash curl -X POST https://api.sparkient.ai/api/v1/decision-types \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "content_moderation", "description": "Should this user-generated content be approved?", "options": ["approve", "flag", "reject"], "reason_codes": ["safe_content", "borderline", "policy_violation", "spam"], "rules": [ { "name": "block_spam_links", "condition": "ctx.link_count > 5", "then": "reject", "reason_code": "spam", "priority": 1 } ] }' ``` ## 3. Make a Decision Now send an input to get a structured decision: ```bash curl -X POST https://api.sparkient.ai/api/v1/decide \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "decision_type": "content_moderation", "input": { "text": "Check out this great new product!", "link_count": 1, "user_reputation_score": 0.85 } }' ``` ### Response ```json { "decision": "approve", "confidence": 0.92, "reason_codes": ["safe_content"], "latency_ms": 4.2, "stage": "rules", "escalate": false, "rules_triggered": [], "request_id": "req_abc123" } ``` ## 4. Train a Model (Optional) Rules handle the obvious cases. For nuanced decisions, train an ML model: 1. **Add training examples** — via the dashboard or the API 2. **Generate synthetic data** — Sparkient's teacher LLM creates additional examples 3. **Train** — one API call triggers the full pipeline (feature engineering → model training → ONNX export) 4. **Deploy** — promote the trained model to production ```bash curl -X POST https://api.sparkient.ai/api/v1/decision-types/{id}/train \ -H "Authorization: Bearer YOUR_API_KEY" ``` Once deployed, subsequent `/decide` calls automatically use the trained model for higher-quality decisions. ## Verify Your Setup You can verify your API connection by hitting the root endpoint: ```bash curl https://api.sparkient.ai/ ``` ```json { "service": "Sparkient API", "by": "Sparkient", "version": "1.0.0", "documentation": "https://docs.sparkient.ai", "openapi": "/openapi.json", "health": "/health" } ``` ## Next Steps - [Authentication](https://docs.sparkient.ai/docs/authentication/) — understand API keys vs Firebase JWT - [Decision Types](https://docs.sparkient.ai/docs/concepts/decision-types/) — learn about options, rules, and versions - [Training Pipeline](https://docs.sparkient.ai/docs/concepts/training/) — how the teacher-student architecture works - [API Reference](https://docs.sparkient.ai/docs/api-reference/) — full endpoint documentation --- # Authentication How to authenticate with the Sparkient API using API keys or Firebase JWT tokens. Sparkient supports two authentication methods. Use whichever fits your use case. ## API Keys (Recommended for Production) API keys are the primary way to authenticate programmatic access. They are scoped to your organization and include built-in rate limiting. ### Getting a Key 1. Sign in to the [Sparkient Dashboard](https://app.sparkient.ai) 2. Navigate to **Settings → API Keys** 3. Click **Create API Key** and copy the generated key ### Using a Key Pass your API key as a Bearer token in the `Authorization` header: ```bash curl -X POST https://api.sparkient.ai/api/v1/decide \ -H "Authorization: Bearer sk_live_abc123..." \ -H "Content-Type: application/json" \ -d '{ "decision_type": "my_type", "input": { "text": "hello" } }' ``` ### Key Format API keys follow the format `sk_live_` followed by a random string. They are: - **Hashed at rest** — stored as HMAC-SHA256 hashes with per-key salts. The raw key is never stored. - **Rate-limited** — each key has a configurable rate limit (default: 600 requests/minute). - **Organization-scoped** — all resources accessed through a key are filtered to your organization. ### Key Rotation To rotate a key: 1. Create a new API key in the dashboard 2. Update your application to use the new key 3. Revoke the old key > **Note:** There is no downtime during rotation — both keys work simultaneously until the old one is revoked. ## Firebase JWT (Dashboard & Frontend) The Sparkient Dashboard uses Firebase Authentication for user sessions. This is primarily for the dashboard UI and is not recommended for server-to-server integration. ### How It Works 1. Users sign in via email/password, Google OAuth, or GitHub OAuth 2. Firebase issues a JWT (ID token) 3. The dashboard sends this token as `Authorization: Bearer ` 4. The API verifies the token with Firebase Admin SDK 5. On first login, a user record is auto-provisioned and linked to an organization ### When to Use | Method | Best For | |:-------|:---------| | **API Key** | Backend services, scripts, CI/CD, production integrations | | **Firebase JWT** | Dashboard sessions, frontend apps with user login | ## Error Responses | Status | Meaning | What to Do | |:------:|:--------|:-----------| | `401` | Missing or invalid credentials | Check your API key or re-authenticate | | `403` | Insufficient permissions | Ensure the key has access to the requested resource | | `429` | Rate limit exceeded | Back off and retry after the limit window resets (1 minute) | All error responses follow a consistent envelope format: ```json { "error": { "code": "unauthorized", "message": "Invalid or expired API key" } } ``` ### Rate Limit Headers API key requests include rate limit headers on every response: | Header | Description | |--------|-------------| | `X-RateLimit-Limit` | Maximum requests per window | | `X-RateLimit-Remaining` | Requests remaining in current window | | `X-RateLimit-Reset` | Unix timestamp when the window resets | | `Retry-After` | Seconds to wait (only on 429 responses) | ## Security Best Practices - **Never expose API keys in client-side code.** Use them only in server-side applications. - **Use environment variables** to store keys — never commit them to source control. - **Rotate keys regularly** and revoke any keys that may have been compromised. - **Use separate keys** for development and production environments. --- # Decision Types Define what decisions your application needs to make. A **decision type** is the core building block of Sparkient. It defines a specific kind of decision your application needs to make — content moderation, fraud detection, agent action gating, or anything else. ## Anatomy of a Decision Type Every decision type has: | Field | Description | |:------|:------------| | **Name** | Unique identifier (e.g., `content_moderation`). Used in API calls. | | **Description** | Human-readable explanation of what this decision does. | | **Options** | The possible outcomes (e.g., `["approve", "flag", "reject"]`). | | **Reason Codes** | Why a particular decision was made (e.g., `["safe_content", "spam"]`). | | **Rules** | Hard-coded CEL rules that fire before the ML classifier. | | **Input Schema** | Optional JSON Schema to validate inputs before processing. | ## Creating a Decision Type ```bash curl -X POST https://api.sparkient.ai/api/v1/decision-types \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "agent_action_gate", "description": "Should an AI agent proceed with this action?", "options": ["act", "ask_user", "escalate", "block"], "reason_codes": ["safe_action", "needs_confirmation", "high_risk"], "rules": [ { "name": "block_destructive", "condition": "ctx.action_type == \"delete\" && ctx.scope == \"all\"", "then": "block", "reason_code": "high_risk", "priority": 1 } ] }' ``` ## Versioning Decision types are **immutable by version**. When you update a decision type (change options, rules, or thresholds), a new version is created. The active version is always the latest. This means: - You can roll back by re-activating an older version - Training history is tied to specific versions - Deployed models reference the version they were trained on ## Confidence Thresholds You can configure how confident the classifier must be before making a decision autonomously: ```json { "confidence_thresholds": { "auto_decide": 0.85, "escalation": 0.5 } } ``` - **Above `auto_decide`** — the classifier's decision is returned directly - **Between `escalation` and `auto_decide`** — depends on the escalation policy - **Below `escalation`** — always escalates to the LLM fallback --- # Decision Pipeline How rules, ML, and LLM escalation work together to make fast decisions. The decision pipeline is the core of Sparkient. Every call to `/decide` flows through three stages, each progressively more powerful — and only as far as needed. ## The Three Stages ``` Input → [1. Rules] → [2. Classifier] → [3. Escalation] → Response < 1ms < 100ms 150ms+ ``` ### Stage 1: Hard Rules (CEL) **Latency: < 1ms** CEL rules are evaluated first. If any rule matches, the decision is returned immediately. This is the fastest path — pure logic, no ML involved. Use this for: - Compliance requirements ("always block amounts over $50,000") - Known patterns ("reject if the user is banned") - Rate limiting ("escalate if more than 10 requests in 1 minute") ### Stage 2: ML Classifier (ONNX) **Latency: < 100ms (typically 5–30ms)** If no rules match and a trained model is deployed, the classifier runs inference. It uses the ONNX-exported LightGBM model with pre-computed features and optional text embeddings. The classifier returns a decision along with: - **Confidence score** (0.0 to 1.0) - **Class probabilities** for all options - **Reason codes** from the training data If the confidence is above the `auto_decide` threshold, the decision is returned. If it's below the `escalation` threshold, it moves to Stage 3. ### Stage 3: LLM Escalation (Gemini) **Latency: 150ms–3s** The fallback for low-confidence decisions. Gemini receives the input and decision type context and produces a structured decision with explanation. This stage includes: - Automatic retry with exponential backoff - Structured output parsing - Timeout protection > **Note:** In practice, a well-trained model escalates less than 5% of decisions. The LLM is a safety net, not the primary path. ## Response Format Every decision — regardless of which stage produced it — returns the same structured format: ```json { "decision": "approve", "confidence": 0.94, "reason_codes": ["safe_content"], "latency_ms": 8.3, "stage": "classifier", "escalate": false, "fallback_used": false, "rules_triggered": [], "class_probabilities": { "approve": 0.94, "flag": 0.04, "reject": 0.02 }, "request_id": "req_abc123" } ``` The `stage` field tells you which stage produced the decision: - `"rules"` — a hard rule matched - `"classifier"` — the ML model decided - `"escalation"` — the LLM fallback was used - `"fallback"` — the LLM escalation was triggered due to an error ## Latency Breakdown | Stage | Typical Latency | When It Runs | |:------|:---------------:|:-------------| | Rules | 0.1–0.5ms | Always (first check) | | Feature extraction | 1–5ms | If no rule matched | | Text embedding | 2–8ms | If input has text fields | | ONNX inference | 0.5–2ms | If model is deployed | | **Total (no escalation)** | **5–30ms** | **95%+ of requests** | | LLM escalation | 150–3000ms | Low-confidence or no model | --- # Rules CEL-based hard rules for deterministic, sub-millisecond decisions. **Rules** are the fastest stage of the decision pipeline. They evaluate in sub-millisecond time using the [Common Expression Language (CEL)](https://cel.dev/) and produce deterministic, explainable outcomes. ## How Rules Work Rules are evaluated **before** the ML classifier. If any rule matches the input, the decision is returned immediately — no ML inference needed. Each rule specifies: | Field | Description | |:------|:------------| | `name` | Human-readable identifier | | `condition` | CEL expression evaluated against `ctx` (the input data) | | `then` | The decision to return if the condition is true | | `reason_code` | Why this decision was made | | `priority` | Lower numbers evaluate first (1 = highest priority) | ## Writing CEL Expressions All input fields are available under the `ctx` namespace: ```js // Simple comparison ctx.amount > 10000 // String matching ctx.action_type == "delete" // Combining conditions ctx.user_verified == true && ctx.risk_score < 0.3 // List operations ctx.tags.exists(t, t == "urgent") // Nested access ctx.metadata.source == "api" ``` ## Rule Evaluation Order Rules are evaluated in **priority order** (lowest number first). The first rule that matches wins. ```json [ { "name": "block_high_risk", "condition": "ctx.risk_score > 0.95", "then": "block", "reason_code": "extreme_risk", "priority": 1 }, { "name": "auto_approve_verified", "condition": "ctx.user_verified == true && ctx.amount < 100", "then": "approve", "reason_code": "trusted_user", "priority": 2 } ] ``` If no rules match, the decision falls through to the ML classifier. ## When to Use Rules vs ML | Use Rules When | Use ML When | |:---------------|:------------| | The logic is simple and deterministic | The decision requires nuance or pattern recognition | | You need guaranteed outcomes for specific conditions | Edge cases are hard to enumerate manually | | Compliance requires exact, auditable logic | The decision should improve over time with data | | Sub-millisecond latency is critical | Sub-100ms is fast enough | Rules and ML work together — rules handle the obvious cases instantly, and the ML classifier handles everything else. ## Validation Rules are validated at creation time: - CEL syntax must be valid - The `then` value must match one of the decision type's options - The `reason_code` must match one of the allowed reason codes --- # Training How Sparkient compiles LLM intelligence into fast ML models. Sparkient's training pipeline uses a **teacher-student architecture**: a large language model (the teacher) generates training data, and a small, fast model (the student) learns to replicate its decisions. ## The Training Pipeline ``` Define Decision Type ↓ Generate Examples (Gemini teacher) ↓ Label Examples (Gemini teacher) ↓ Augment Rare Classes (Gemini teacher) ↓ Feature Engineering (auto-detected) ↓ Text Encoding (DeBERTa-v3) ↓ Model Training (LightGBM + Optuna) ↓ ONNX Export ↓ Deploy to Production ``` ## Synthetic Data Generation You don't need to bring your own training data. Sparkient's teacher LLM generates realistic, diverse examples based solely on your decision type definition. 1. **Generation** — Gemini creates input examples that cover the full space of possible decisions 2. **Labelling** — Gemini assigns decisions and reason codes to each example, using the same reasoning a human expert would apply 3. **Augmentation** — Gap analysis identifies underrepresented classes, and Gemini generates targeted examples to balance the dataset ## Feature Engineering Features are auto-detected from your input schema: | Input Type | Feature Strategy | |:-----------|:-----------------| | Numbers | Z-score normalization | | Booleans | Binary encoding | | Strings (short) | Categorical encoding | | Strings (long) | Text embedding (Model2Vec, 256-dim, sub-ms) | | Arrays | Length + aggregation features | | Nested objects | Flattened with dot notation | For text-heavy decisions, a **DeBERTa-v3-small** encoder is fine-tuned on your data and its embeddings are stacked as features for the final classifier. ## Model Training The final classifier is **LightGBM** with **Optuna** hyperparameter tuning: - Automatic cross-validation - Bayesian hyperparameter optimization - Multi-class classification with probability calibration - Export to **ONNX** format for portable, fast inference ## Triggering Training ```bash curl -X POST https://api.sparkient.ai/api/v1/decision-types/{id}/train \ -H "Authorization: Bearer YOUR_API_KEY" ``` Training runs asynchronously. You can check the status via the dashboard or the policies endpoint. ## Deploying a Model After training completes, a **policy** is created containing the trained model. To activate it: ```bash curl -X POST https://api.sparkient.ai/api/v1/decision-types/{id}/policies/{policy_id}/deploy \ -H "Authorization: Bearer YOUR_API_KEY" ``` Once deployed, subsequent `/decide` calls use the trained model instead of falling through to the LLM escalation path. --- # Edge Deployment Run Sparkient decisions locally with zero cloud dependencies. The **Edge SDK** lets you export a trained decision type as a standalone bundle and run it locally — on-device, on-premise, or in air-gapped environments. Zero network calls, zero cloud dependencies. ## How It Works A Sparkient edge bundle contains everything needed to make decisions offline: | Component | Purpose | |:----------|:--------| | ONNX model | The compiled ML classifier | | CEL rules | Hard rules, evaluated first | | Feature config | How to extract features from input | | Metadata | Decision type name, options, version | The entire bundle is a single ZIP file, typically 1–5 MB. ## Export a Bundle ```bash curl -X GET https://api.sparkient.ai/api/v1/decision-types/{id}/export \ -H "Authorization: Bearer YOUR_API_KEY" \ -o my_decision_type.zip ``` ## Use in Python ```python from edge import load_bundle, EdgePredictor # Load the exported bundle predictor = EdgePredictor.from_bundle("my_decision_type.zip") # Make a decision (< 10ms, no network) result = predictor.predict({ "text": "Check out this product", "user_score": 0.85, "link_count": 1 }) print(result.decision) # "approve" print(result.confidence) # 0.94 print(result.reason_codes) # ["safe_content"] print(result.latency_ms) # 3.2 ``` ## Dependencies The edge predictor requires only: ``` onnxruntime cel-python numpy ``` No FastAPI, no database, no Redis, no cloud SDKs. It's designed for constrained environments. ## Use Cases - **On-device inference** — Mobile apps, IoT devices, embedded systems - **Air-gapped environments** — Government, military, healthcare systems without internet - **Ultra-low latency** — Eliminate network round-trip for sub-10ms decisions - **Cost optimization** — Zero API calls after the initial bundle download - **Offline-first applications** — Apps that need to work without connectivity ## Updating When you retrain and deploy a new model, export a new bundle and replace the old one. The edge predictor loads the latest bundle on initialization. --- # API Reference Complete reference for all Sparkient API endpoints. The Sparkient API is a RESTful JSON API. All endpoints are prefixed with `/api/v1` and require authentication via API key or Firebase JWT. **Base URL:** `https://api.sparkient.ai/api/v1` ## Endpoints Overview | Group | Endpoints | Description | |:------|:----------|:------------| | **Decisions** | `POST /decide`, `POST /decide/batch` | Make single or batch decisions | | **Decision Types** | CRUD on `/decision-types` | Create, list, get, update, delete decision types | | **Examples** | `/decision-types/{id}/examples` | Manage training examples | | **Training** | `/decision-types/{id}/train` | Trigger model training | | **Policies** | `/decision-types/{id}/policies` | List and deploy trained models | | **Logs** | `/decision-types/{id}/logs` | Query decision history | | **Export** | `/decision-types/{id}/export` | Download edge bundles | | **Auth** | `/auth/me`, `/auth/org` | User and organization management | | **API Keys** | `/api-keys` | Create, list, and revoke API keys | | **Metrics** | `/metrics` | Organization-level aggregate statistics | | **System** | `/health`, `/ready` | Health and readiness probes | > **Note:** Interactive endpoint documentation is generated automatically from the OpenAPI specification. If you're viewing a freshly built docs site, the detailed endpoint pages will appear below once the OpenAPI spec has been processed. ## Common Patterns ### Authentication All requests require a Bearer token: ```bash -H "Authorization: Bearer YOUR_API_KEY" ``` ### Error Responses All errors follow a consistent envelope format with a machine-readable `code` field: ```json { "error": { "code": "decision_type_not_found", "message": "Decision type 'nonexistent' not found." } } ``` Validation errors (422) include a `details` array: ```json { "error": { "code": "validation_error", "message": "Request validation failed.", "details": [ { "type": "missing", "loc": ["body", "decision_type"], "msg": "Field required" } ] } } ``` | Status | Code | Description | |--------|------|-------------| | 400 | `bad_request` | Malformed request | | 401 | `unauthorized` | Missing or invalid credentials | | 403 | `forbidden` | Insufficient permissions | | 404 | `not_found` | Resource not found | | 404 | `decision_type_not_found` | Decision type does not exist | | 413 | `payload_too_large` | Request body exceeds size limit | | 422 | `validation_error` | Request validation failed | | 429 | `rate_limited` | Rate limit exceeded | | 500 | `internal_error` | Unexpected server error | ## Rate Limiting API key requests include rate limit headers on every response: | Header | Description | |--------|-------------| | `X-RateLimit-Limit` | Maximum requests per window | | `X-RateLimit-Remaining` | Requests remaining in current window | | `X-RateLimit-Reset` | Unix timestamp when the window resets | | `Retry-After` | Seconds to wait (only on 429 responses) | ## Pagination List endpoints support pagination via query parameters: | Parameter | Default | Range | Description | |-----------|---------|-------|-------------| | `page` | 1 | ≥ 1 | Page number | | `page_size` | 20 | 1–100 | Items per page | Paginated responses return: ```json { "items": ["..."], "total": 42, "page": 1, "page_size": 20, "pages": 3 } ``` --- # API Endpoints All endpoints from the OpenAPI specification (`https://docs.sparkient.ai/openapi.json`). ## System | Method | Path | Summary | |--------|------|---------| | GET | `/` | Root — API info landing page | | GET | `/health` | Health — Liveness probe | | GET | `/ready` | Readiness — Checks DB, Redis, and model availability | ## Auth | Method | Path | Summary | |--------|------|---------| | GET | `/api/v1/auth/me` | Get the currently authenticated user and organization | | PUT | `/api/v1/auth/me` | Update the current user's name | | PUT | `/api/v1/auth/org` | Update the organization name (owner only) | ## API Keys | Method | Path | Summary | |--------|------|---------| | GET | `/api/v1/api-keys` | List all API keys for the organization | | POST | `/api/v1/api-keys` | Create a new API key (raw key returned once) | | DELETE | `/api/v1/api-keys/{key_id}` | Soft-delete an API key (owner only) | ## Decision Types | Method | Path | Summary | |--------|------|---------| | POST | `/api/v1/decision-types` | Create a new decision type with its first version | | GET | `/api/v1/decision-types` | List all decision types with pagination | | GET | `/api/v1/decision-types/{decision_type_id}` | Get a decision type by ID with its active version | | PUT | `/api/v1/decision-types/{decision_type_id}` | Update a decision type (creates new version if logic fields change) | | DELETE | `/api/v1/decision-types/{decision_type_id}` | Soft-delete a decision type | | GET | `/api/v1/decision-types/{decision_type_id}/versions` | List all versions for a decision type | | GET | `/api/v1/decision-types/{decision_type_id}/versions/{version_id}` | Get a specific version | ## Decisions | Method | Path | Summary | |--------|------|---------| | POST | `/api/v1/decide` | Make a single decision | | POST | `/api/v1/decide/batch` | Make multiple decisions in parallel (max 50) | ## Examples | Method | Path | Summary | |--------|------|---------| | POST | `/api/v1/decision-types/{decision_type_id}/examples` | Upload training examples | | GET | `/api/v1/decision-types/{decision_type_id}/examples` | List training examples with filtering and pagination | | POST | `/api/v1/decision-types/{decision_type_id}/examples/generate` | Generate synthetic training examples | | DELETE | `/api/v1/decision-types/{decision_type_id}/examples/{example_id}` | Delete a training example | ## Training & Policies | Method | Path | Summary | |--------|------|---------| | POST | `/api/v1/decision-types/{decision_type_id}/train` | Trigger model training | | GET | `/api/v1/decision-types/{decision_type_id}/policies` | List trained model policies | | GET | `/api/v1/decision-types/{decision_type_id}/policies/{policy_id}` | Get a specific policy | | POST | `/api/v1/decision-types/{decision_type_id}/policies/{policy_id}/deploy` | Deploy a trained policy to production | ## Logs & Metrics | Method | Path | Summary | |--------|------|---------| | GET | `/api/v1/decision-types/{decision_type_id}/logs` | Query decision logs | | GET | `/api/v1/decision-types/{decision_type_id}/metrics` | Get metrics for a decision type | | GET | `/api/v1/metrics` | Get organization-level aggregate metrics | ## Export | Method | Path | Summary | |--------|------|---------| | GET | `/api/v1/decision-types/{decision_type_id}/export` | Export edge bundle (ZIP) |