Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content
API Reference

API Reference

Base URL: https://api.minima.sh. Base path: /v1. All request and response bodies are JSON. Interactive OpenAPI docs are served at https://api.minima.sh/docs.

Authentication

Minima uses pass-through auth: present your own Mubit API key as a bearer token. There is no separate Minima key — Minima forwards the key to Mubit to read and write your task → model → outcome history on your behalf.

Authorization: Bearer mbt_<instance>_<keyid>_<secret>

A missing or invalid key returns 401. Your Mubit key determines which Mubit instance Minima reads and writes — it's your data boundary. Only two endpoints work without a key: GET /v1/health (service liveness) and GET /v1/capabilities (structural metadata).

user_id and namespace are scoping fields within your Mubit instance, not auth boundaries — use them to partition recall and learning across teams, projects, or environments.

Errors

Errors are returned as application/problem+json (RFC 7807-style):

{ "type": "about:blank", "title": "No candidate models", "status": 422,
  "detail": "no models match the supplied constraints" }
StatusTitleWhen
400Invalid requestRequest body fails validation.
401UnauthorizedMissing or invalid Mubit key.
422No candidate modelsConstraints eliminated every catalog model.
ℹ️Note

POST /v1/feedback does not error on an unknown recommendation_id. It returns 200 with accepted: false and an unknown_recommendation warning, so retried or cross-instance feedback fails safely.


POST /v1/recommend

core

Recommend a model for a single task.

Request — RecommendRequest

FieldTypeDefaultNotes
taskTaskInputrequiredThe task to route (see below).
cost_quality_tradeofffloat 0–105.00 = cheapest acceptable, 10 = highest quality. Sets the quality threshold τ.
constraintsConstraints{}Hard limits on the candidate set (see below).
user_idstring | nullnullWithin-account actor label. Scopes recall.
namespacestring | nullnullWithin-account sub-scope (team / project / environment). Isolates recall and learning.
max_candidatesint 1–648Cap on candidates considered.
allow_llm_escalationbooltrueAllow the cheap-LLM reasoner when evidence is thin.
explainbooltrueInclude evidence[] refs on each ranked model.
baseline_model_idstring | nullnullThe model you would have used without Minima. Powers the honest vs_declared baseline in GET /v1/savings.
incumbent_model_idstring | nullnullThe model currently holding a warm prompt cache for this conversation. Lets Minima price cache stickiness honestly instead of naively switching away from cached context.

TaskInput

FieldTypeDefaultNotes
taskstringrequiredRaw task/prompt text; embedded by Mubit for recall.
task_typeenum | nullnullcode | summarization | extraction | qa | reasoning | classification | translation | creative | rag | tool_use | other. Heuristic-classified if omitted.
difficultyenum | nullnulltrivial | easy | medium | hard | expert.
expected_input_tokensint ≥ 0 | nullnullFeeds the cost estimate; a per-task-type default is used if omitted.
expected_output_tokensint ≥ 0 | nullnullFeeds the cost estimate.
tagsstring[][]Propagated to Mubit env_tags (e.g. lang:python) for version-aware recall.

Constraints (all optional)

FieldTypeNotes
allowed_providersstring[] | nullWhitelist by provider.
candidate_modelsstring[] | nullRestrict to these model ids.
excluded_modelsstring[] | nullBlacklist by model id.
max_cost_per_callfloat ≥ 0 | nullUSD hard filter on estimated cost.
min_qualityfloat 0–1 | nullPredicted-success floor; raises τ.
require_prompt_cachingboolKeep only models that support prompt caching.
max_latency_msint > 0 | nullDrop candidates whose observed latency (p75 from similar past outcomes) exceeds this. A model with no latency history is never excluded.
require_context_windowint > 0 | nullKeep only models with at least this context window.

Response — RecommendResponse

FieldTypeNotes
recommendation_idstringQuote this back to POST /v1/feedback.
recommended_modelRankedModelThe chosen model.
rankedRankedModel[]Every candidate, sorted by final score.
fallback_modelRankedModel | nullA more reliable retry target.
confidencefloat 0–1Overall confidence in the pick.
decision_basisenummemory | prior | llm — which path produced the pick.
threshold_usedfloatThe quality threshold τ applied.
classified_task_typeenumFinal task type used.
classified_difficultyenumFinal difficulty used.
catalog_versionstringCatalog version that priced the candidates.
catalog_staleboolPrices older than the staleness window.
latency_msintMinima-side recommendation latency.
warningsstring[]See Warnings below.
selection_policyenumargmin (deterministic cheapest-eligible, the default) | epsilon_softmax (account opted into bounded exploration within the eligible set).
recommended_actionsstring[]Near-free cost-saving actions to apply (e.g. enable_prompt_cache).

RankedModel

FieldTypeNotes
model_idstring
providerstring
predicted_successfloat 0–1Probability the model clears the task.
est_cost_usdfloat ≥ 0Estimated cost for this request, per the chosen cost basis.
est_cost_breakdownobjectKeys depend on the basis: {rescaled, obs_output_tokens}, {observed_avg}, or {input, output}. See Cost-basis tiers.
scorefloatFinal objective score; the sorting key.
rationalestringHuman-readable reason (tags cost as obs or est).
decision_basisenumPer-model basis: memory | prior | llm.
evidenceEvidenceRef[]Recalled neighbors that informed this candidate (empty if explain=false).
supports_prompt_cachingbool
context_windowint
est_latency_msfloat | nullObserved latency percentile from similar past outcomes; null without latency history.
latency_basisstringe.g. observed_p75; empty without latency history.
est_cost_low / est_cost_highfloat | nullCost uncertainty band around est_cost_usd.
cost_band_basisstringHow the band was derived; empty when no band is available.
success_interval_widthfloatWidth of the credible interval on predicted_success — how settled the evidence is.

EvidenceRef

FieldTypeNotes
entry_idstringMubit QueryEvidence.id (used for outcome attribution).
reference_idstring | nullStable reference id.
model_idstringThe model this past outcome was about.
scorefloatRetrieval similarity.
knowledge_confidencefloat 0–1Mubit's reliability estimate for the entry.
observed_successfloat 0–1The recorded quality of that past outcome.
is_staleboolWhether the entry is marked stale.

Warnings

WarningMeaning
cold_startNo recalled outcomes; prior-only.
recall_timeoutMubit recall exceeded the timeout; prior-only.
memory_unavailableRecall errored; prior-only.
prices_staleCatalog prices older than the staleness window.
no_model_meets_thresholdNo candidate cleared τ; recommended the highest-success one.
no_model_within_cost_budgetmax_cost_per_call eliminated all; constraint relaxed for ranking.
no_model_within_latency_budgetmax_latency_ms eliminated every candidate with latency history; constraint relaxed for ranking.
escalation_suggested:<reason>Escalation criteria met (thin_evidence, low_confidence, tie, conflict, wide_interval, low_recall_confidence).
memory_drift:repeatedMubit's drift signals flag this task as a repeating pattern with no new outcomes arriving.
memory_drift:stagnantThe recalled evidence neighborhood is stagnating — same entries recalled, nothing fresh reinforcing them.
exploration_pickThe opt-in exploration policy sampled a different eligible model than the deterministic pick.
reasoner_consultedThe cheap-LLM reasoner was consulted and changed scores.
reasoner_failedThe reasoner errored or returned unusable output; deterministic result used.
reasoner_disabledEscalation suggested but no reasoner is configured.
llm_classifiedThe reasoner refined an ambiguous task classification.

Example

curl -s https://api.minima.sh/v1/recommend \
  -H "authorization: Bearer $MUBIT_API_KEY" \
  -H 'content-type: application/json' -d '{
  "task": {"task": "Write a Python function that merges k sorted linked lists.",
           "task_type": "code", "difficulty": "hard",
           "expected_input_tokens": 180, "expected_output_tokens": 600,
           "tags": ["lang:python"]},
  "cost_quality_tradeoff": 3,
  "constraints": {"min_quality": 0.8, "excluded_models": ["some-deprecated-model"]},
  "namespace": "team-payments"
}' | jq

POST /v1/recommend/workflow

workflow

Recommend a model for each step of a multi-step workflow. Each step runs the same engine independently and gets its own recommendation_id for per-step feedback.

Request — WorkflowRequest

FieldTypeDefaultNotes
stepsWorkflowStep[]requiredThe steps to route.
cost_quality_tradeofffloat 0–105.0Applied to every step.
constraintsConstraints{}Global constraints; each step may override.
user_idstring | nullnull
namespacestring | nullnull
allow_llm_escalationbooltrue

WorkflowStep

FieldTypeNotes
step_idstringCaller-defined id (echoed in the response).
taskTaskInputThe step's task.
constraintsConstraints | nullPer-step override, merged over the global constraints.
depends_onstring[]Declared dependencies (informational; steps are scored independently).

Response — WorkflowResponse

FieldTypeNotes
workflow_recommendation_idstringId for the whole workflow.
stepsStepRecommendation[]{step_id, recommendation: RecommendResponse} per step.
total_est_cost_usdfloatSum of recommended-model costs across steps.
total_est_cost_if_all_premiumfloatSum if each step used its most expensive candidate — the savings baseline.
confidencefloat 0–1Mean step confidence.

See the multi-step workflow example.


POST /v1/feedback

core

Report an outcome and close the learning loop. This reinforces the memories that drove the recommendation and records realized cost/token history that powers the observed and rescaled cost-basis tiers.

Request — FeedbackRequest

FieldTypeDefaultNotes
recommendation_idstringrequiredFrom a prior /recommend (or a workflow step).
chosen_model_idstringrequiredThe model you actually ran (may differ from the recommendation).
outcomeenumrequiredsuccess | partial | failure.
quality_scorefloat 0–1 | nullnullCaller-supplied judge/eval score. A score that flatly contradicts the outcome label (e.g. failure at 0.95) is clamped into a consistent band with a quality_outcome_mismatch warning.
evidence_sourceenum | nullnullWhere the outcome label came from: gate (a deterministic check passed — the only origin that may claim verified-in-production) | judge (an LLM judge scored it) | human (a person asserted it) | none (no real label — the outcome is cost/latency telemetry only and never teaches the success posterior).
error_causeenum | nullnullFor outcome=failure: infra (provider/tooling fault — 429/5xx/timeout; never learned as model quality) | quality (the model's output was wrong).
input_tokensint ≥ 0 | nullnullRealized input tokens — populate this to enable the rescaled cost tier.
output_tokensint ≥ 0 | nullnullRealized output tokens (captures reasoning/thinking) — populate this for the rescaled tier.
actual_cost_usdfloat ≥ 0 | nullnullRealized $/call — enables the observed cost tier.
latency_msint ≥ 0 | nullnull
iterationsint ≥ 0 | nullnullAgent-loop turns to resolution — a token-yield signal recorded on the outcome.
chosen_effortstring | nullnullThe reasoning-effort level actually used, if your stack varies it.
step_outcomesStepOutcome[][]Per-step verdicts for multi-step work (see below). Capped at 32 per call.
verified_in_productionboolfalseDeprecated — send evidence_source: "gate" instead.
judgedbool | nullnullDeprecated — send evidence_source instead (judged: falseevidence_source: "none").
notesstring | nullnull
idempotency_keystring | nullnullDedupe key; derived from recommendation_id + model if omitted.

StepOutcome

Process-level rewards: when a task ran as verifiable steps (e.g. the Minima CLI's gate-checked plan steps), each step's verdict can ride along with the turn-level feedback, teaching the recommender which parts of a task the model handled.

FieldTypeNotes
step_idstringrequired — caller-defined step identity.
step_namestring | nullHuman-readable label.
outcomeenumsuccess | partial | failure.
signalfloat -1–1 | nullOptional scalar reward; derived from the outcome if omitted.
rationalestring | nullWhy — e.g. which check verified it.
directive_hintstring | nullA forward-looking hint for future recall.

Response — FeedbackResponse

FieldTypeNotes
acceptedboolfalse with a warning on failure.
record_idstring | nullThe Mubit id of the upserted outcome record.
reinforced_entry_idsstring[]The neighbor entry ids credited.
updated_confidencefloat | nullMubit's updated knowledge_confidence for the primary entry.
reflection_triggeredboolWhether reflection fired this call.
lesson_promotedboolWhether a durable lesson was promoted.
step_outcomes_recordedintHow many step_outcomes were actually relayed to memory.
warningsstring[]unknown_recommendation, memory_write_failed, reinforcement_failed, lesson_promotion_failed, quality_outcome_mismatch, late_feedback_no_attribution, step_outcomes_capped:<n>, step_outcomes_partial.
ℹ️Note

How late can feedback arrive? A recommendation_id accepts fully-attributed feedback for 7 days. After that the outcome is still accepted and still teaches the recommender (the durable outcome record is written), but the specific recalled neighbors can no longer be credited — the response carries a late_feedback_no_attribution warning.

Example

curl -s https://api.minima.sh/v1/feedback \
  -H "authorization: Bearer $MUBIT_API_KEY" \
  -H 'content-type: application/json' -d '{
  "recommendation_id": "…",
  "chosen_model_id": "claude-haiku-4-5",
  "outcome": "success",
  "quality_score": 0.95,
  "evidence_source": "gate",
  "input_tokens": 180, "output_tokens": 640, "actual_cost_usd": 0.0034,
  "step_outcomes": [
    {"step_id": "tests-pass", "outcome": "success", "rationale": "step_check/deterministic/green"}
  ]
}' | jq

GET /v1/models

The current model catalog (cost + capability priors).

Query parameters

ParamTypeDefaultNotes
providerstringFilter by provider (case-insensitive).
task_typeenumKeep only models with a capability prior for this task type.
max_costfloatKeep only models whose max(input, output) $/Mtok ≤ this.
include_stalebooltruePrefer fresh-priced models when false.

Response

{ models: ModelCard[], catalog_version, refreshed_at, stale }, sorted by input price.

ModelCard fields include: model_id, provider, display_name, input_cost_per_mtok, output_cost_per_mtok, cache_read_cost_per_mtok, supports_prompt_caching, context_window, max_output_tokens, capability_priors, capability_by_task_type, cost_source, cost_fetched_at, cost_stale, capability_source.


GET /v1/strategies

Surfaces the rules Mubit has promoted for a namespace — the "why" behind routing patterns.

Query parameters

ParamTypeDefaultNotes
namespacestringWithin-account sub-scope to read strategies for.
lesson_typesstring[]Filter by lesson type.
max_strategiesint 1–505

Response

{ namespace, lane, strategies: Strategy[], count }, where each Strategy has strategy_id, description, supporting_lesson_count, avg_confidence, avg_reinforcement, dominant_lesson_type, dominant_scope, lesson_ids[].


GET /v1/savings

measurement

What Minima actually saved you. Every recommendation is logged with its counterfactual cost baselines and reconciled with the realized cost you report to /v1/feedback — this endpoint aggregates that ledger for your account.

Two baselines are always reported side by side, explicitly labeled: vs premium (the most expensive candidate that was scored for each request — generous; overstates savings if you'd never have used the premium model) and vs declared (your own stated default via baseline_model_id — honest, but only present on requests where you declared one). Estimated and realized figures are never mixed into one number.

Query parameters

ParamTypeDefaultNotes
namespacestringRestrict to one namespace.
daysfloat >0–36530Lookback window (must be greater than 0).
group_byenumcluster | task_type | lane — optional breakdown.

Response

FieldTypeNotes
summary.estimatedobjectn, cost_recommended_usd, cost_premium_usd, savings_vs_premium_usd, plus n_declared / cost_declared_usd / savings_vs_declared_usd over the declared-baseline subset.
summary.realizedobjectA different field set over the reconciled subset (feedback received with actual_cost_usd): n_reconciled, realized_cost_usd, est_cost_recommended_usd, est_cost_premium_usd, savings_vs_premium_est_usd, plus n_declared / est_cost_declared_usd / savings_vs_declared_est_usd — your realized cost measured against the estimated baselines.
healthobjectrecommendations, feedback_coverage (share of recommendations that ever got feedback — the number that decides how much to trust realized), late_feedback_share, escalation_rate, exploration_share, epsilon_policy_share.
groupsarrayPer-group_by key: the same summary + health.
curl -s "https://api.minima.sh/v1/savings?days=30&group_by=task_type" \
  -H "authorization: Bearer $MUBIT_API_KEY" | jq '.summary, .health'
ℹ️Note

Send baseline_model_id on your /v1/recommend calls and realized actual_cost_usd on your /v1/feedback calls — they turn the savings report from an estimate into a measurement.


GET /v1/calibration

measurement

Is predicted_success telling the truth for your traffic? Compares each recommendation's predicted success against the realized outcome you reported, per task type.

Query parameters

ParamTypeDefaultNotes
namespacestringRestrict to one namespace.
daysfloat >0–36530Lookback window (must be greater than 0).

Response

FieldTypeNotes
reportsarrayPer slice (first entry is global, then each task type): n, ece (expected calibration error — 0 is perfect), ece_shrunk (sparse slices pulled toward the global estimate so 3 feedbacks don't read as a verdict), ece_quality (quality-score-weighted variant), and reliability bins (lo, hi, n, avg_predicted, avg_realized).
drift_flagsarraySustained prediction drift per (cluster, model)direction is over_predicting (the model got worse than the evidence says; the expensive failure mode) or under_predicting.
healthobjectSame routing-health rates as /v1/savings.
curl -s "https://api.minima.sh/v1/calibration?days=30" \
  -H "authorization: Bearer $MUBIT_API_KEY" | jq '.reports[] | {slice_key, n, ece, ece_shrunk}'

GET /v1/policy-value

measurement

Regret-vs-oracle: doubly-robust off-policy estimates of what alternative routing policies would have been worth on your own traffic, computed over trusted-provenance reconciled decisions. The counterfactual numbers are only as good as the log's stochasticity and label trust — both are surfaced so the estimate can never quietly overclaim.

Query parameters

ParamTypeDefaultNotes
namespacestringRestrict to one namespace.
daysfloat >0–36530Lookback window.

Response

{ org_id, since, days, namespace, report }, where report is a RegretReport:

FieldTypeNotes
n_trustedintReconciled decisions with trusted labels (gate/human provenance) the estimate rests on.
n_total_reconciledintAll reconciled decisions in the window.
stochastic_sharefloatShare of trusted rows logged with a non-degenerate propensity — the fraction of the log that is genuinely counterfactual-capable.
policiesPolicyEstimate[]Per policy (e.g. deployed, cheapest-eligible, always-premium): estimated success, cost, and matched share.
regret_vs_oraclefloatModel-based oracle success minus the deployed policy's empirical success — how much quality was left on the table.

POST /v1/diagnose

memory

Failure lessons matching an error — "here's how this failed before", straight from your Mubit memory lane. The Minima CLI's recovery ladder calls this on a verified failure so the retry is briefed by memory. Degrades like the recommend hot path: a Mubit outage returns an empty list plus a memory_unavailable warning, never a 500.

Request — DiagnoseRequest

FieldTypeDefaultNotes
error_textstringrequiredThe error/failure output to match.
error_typestring | nullnullOptional classifier hint.
limitint 1–255Max lessons returned.
namespacestring | nullnullResolves to lane minima:<namespace>.
user_idstring | nullnull

Response — DiagnoseResponse

{ namespace, lane, failure_lessons: FailureLesson[], summary, total_failure_lessons, warnings[] }, where each FailureLesson carries lesson_id, content, lesson_type, importance, confidence.

curl -s https://api.minima.sh/v1/diagnose \
  -H "authorization: Bearer $MUBIT_API_KEY" \
  -H 'content-type: application/json' \
  -d '{"error_text": "TypeError: cannot read properties of undefined (reading map)", "limit": 3}' | jq

GET /v1/memory/health

memory

Per-namespace memory hygiene: entry counts, stale entries, contradictions, low-confidence entries, and promotion candidates — a diagnostics view of the memory your routing runs on. Same graceful degradation as /v1/diagnose.

Query parameters

ParamTypeDefaultNotes
namespacestring | nullResolves to lane minima:<namespace>.
stale_threshold_daysint 1–36530Age beyond which an entry counts as stale.

Response — MemoryHealthResponse

{ namespace, lane, entry_counts: {type: count}, stale_entries, contradictions, low_confidence_count, promotion_candidates, section_health, warnings[] }.

curl -s "https://api.minima.sh/v1/memory/health?stale_threshold_days=30" \
  -H "authorization: Bearer $MUBIT_API_KEY" | jq

GET /v1/capabilities

Server feature handshake: which optional endpoints and constraint fields the running server honors. Read it once at startup and cache it per session — gate optional features (like workflow routing) on what the server actually supports instead of guessing. No auth required — this is structural metadata, not account-scoped data.

Response — CapabilitiesResponse

FieldTypeNotes
planboolPOST /v1/plan (goal → Delegation DAG) is available. Currently false.
workflowboolPOST /v1/recommend/workflow is available.
api_versionstringRunning server version.
honored_constraintsstring[]Constraint fields the engine actively filters on (not merely accepts).
curl -s https://api.minima.sh/v1/capabilities | jq
{
  "plan": false,
  "workflow": true,
  "api_version": "0.13.0",
  "honored_constraints": ["candidate_models", "excluded_models", "max_cost_per_call",
    "min_quality", "require_prompt_caching", "max_latency_ms",
    "require_context_window", "allowed_providers"]
}

GET /v1/health

Always returns 200; reports degraded state in the body. Doesn't require a key (an unauthenticated probe gets service liveness; a key-bearing probe additionally confirms your account's memory reachability).

{
  "status": "ok",
  "mubit": {"reachable": true, "latency_ms": 12, "endpoint": "https://api.mubit.ai", "org_id": "…"},
  "auth": "passthrough",
  "catalog": {"version": "…", "cost_source": "litellm", "stale": false, "models": 42},
  "reasoner": {"provider": "gemini", "configured": true},
  "version": "0.13.0"
}

An unauthenticated probe (no key) returns "mubit": {"reachable": null, "scope": "unauthenticated"} and status: "ok" — liveness only. status is degraded only when a key-bearing probe finds your memory backend unreachable (mubit.reachable == false); in that state /recommend still serves prior-only recommendations.