Skip to content

GET /v1/decisions/{request_id}

Pull the full routing audit for a single chat-completion request, keyed by the x-request-id header that the gateway echoes on every response. Useful for correlating an entry in your application logs with the exact provider, model, candidates, and confidence that Floopy chose for it.

This endpoint never produces a decision_trace row of its own — it only reads.

GET https://api.floopy.ai/v1/decisions/{request_id}
Authorization: Bearer <your-floopy-api-key>
  • Permission: read_permission on the API key (HTTP method maps to GET → read_permission).
  • Available on all plans.
  • We are rolling this endpoint out gradually; an organization that has not been enabled yet receives 404 not_found, with bytes identical to a non-existent request. Contact support for early access.
FieldTypeRequiredConstraints
request_idstring (UUID v4)YesValidated with strict UUID parse. Malformed input returns 400 invalid_request_id.
{
"request_id": "0c4a1d3f-7bea-4a1f-8b6e-2c0a8e4d3f10",
"request_created_at": "2026-05-05T17:42:11Z",
"session_id": "sess_demo_1",
"routing_strategy": "feedback_driven",
"phase": "auto",
"weights": { "session": 0.5, "auto": 0.3, "manual": 0.1, "benchmark": 0.1 },
"candidates": [
{ "provider": "openai", "model": "gpt-5.4-mini", "score": 0.81 },
{ "provider": "anthropic", "model": "claude-sonnet-4", "score": 0.78 }
],
"filtered": [
{ "provider": "openai", "model": "gpt-5.4", "reason": "constraint_max_cost_increase", "score": 0.86 }
],
"winner": { "provider": "openai", "model": "gpt-5.4-mini" },
"reason": "dispatched",
"confidence": 0.78,
"confidence_reason": "ok",
"exploration_rate_effective": 0.05,
"used_shared_pool_prior": false,
"outcome": {
"status": 200,
"latency_ms": 412,
"cost_micro_usd": 230,
"cache_hit": false,
"threat_blocked": false,
"fallback_used": false
},
"evidence": {
"samples": 412,
"top2_score_gap": 0.07,
"outcome_variance": 0.04,
"recent_regressions": { "kind": "exact", "exact": 1 },
"last_regression_at": "2026-05-04T18:25:00Z"
},
"explanation": {
"text": "Floopy routed this request to openai/gpt-5.4-mini based on 412 historical samples and a moderate confidence of 0.78. The next candidate scored within 0.07 points and outcome variance has been stable. One regression was recorded in the last 7 days.",
"template_id": "feedback_driven_moderate_confidence"
}
}

The response also carries a Content-Language header echoing the locale used to render explanation.text — see the Decision Explanation feature.

FieldTypeDescription
request_idUUIDThe id from the x-request-id response header.
request_created_atISO8601Server-side request timestamp (UTC).
session_idstring | nullThe floopy-session-id header value, if any.
routing_strategystringName of the strategy that ran (feedback_driven, smart_cost, fallback, round_robin, weighted, latency_based, legacy_model).
phasestring | nullFeedback-Driven phase (day0, auto, nps); null for non-Feedback-Driven runs.
weightsobject | nullSignal weights at decision time (Feedback-Driven only).
candidatesarrayModels considered, with the routing score the strategy assigned each.
filteredarrayCandidates removed during filtering. reason is a closed enum (see below).
winnerobject | nullThe dispatched (provider, model). null when no candidate could be selected.
reasonstringdispatched, exhausted, or no_enabled_targets.
confidencenumber | nullRouter’s self-reported confidence in the winner, in [0.0, 1.0]. null means no router was invoked (e.g. cache hit). See Confidence methodology.
confidence_reasonstring | nullWhy this confidence value — ok, cap_day0, cap_shared, no_router_invoked, insufficient_samples, single_candidate.
exploration_rate_effectivenumberEffective exploration rate for this request.
used_shared_pool_priorbooleanWhether the routing decision drew on cross-tenant priors.
outcome.statusintegerHTTP status of the underlying chat completion.
outcome.latency_msinteger | nullEnd-to-end latency in milliseconds.
outcome.cost_micro_usdintegerProvider cost for the request in micro-USD.
outcome.cache_hitbooleanWhether the response was served from cache.
outcome.threat_blockedboolean | nullWhether the LLM firewall blocked the request.
outcome.fallback_usedbooleanWhether a fallback target was used.
evidenceobject | nullInputs that drove the confidence number, surfaced for audit (Feedback-Driven and Smart-Cost only). null when no router was invoked. See Confidence methodology.
evidence.samplesintegerRolling sample count n_samples over the winner.
evidence.top2_score_gapnumberScore gap between winner and runner-up.
evidence.outcome_variancenumberRolling outcome variance for the winner.
evidence.recent_regressionstagged unionBucketed regression count over the winner’s (provider, model) in the last 7 days. Tagged union with kind: "exact" and field exact for n < 10, or kind: "at_least" and field at_least for 10 and 50 thresholds.
evidence.last_regression_atISO8601 | nullTimestamp of the most recent regression in the 7-day window, rounded to the nearest 5-minute boundary. null when no regression exists.
explanationobject | nullHuman-readable explanation of the routing decision, rendered at read time in the request’s Accept-Language (falling back to en). null when no router was invoked. See Decision Explanation.
explanation.textstringPlain-prose paragraph (≤ 600 characters) describing the decision. Never references prompt content.
explanation.template_idstringClosed-enum template id that was rendered. See the template-id taxonomy.

filtered[].reason values: circuit_breaker_open, rate_limited, constraint_max_cost_increase, constraint_max_regression, constraint_confidence_below_threshold, constraint_min_samples, constraint_high_variance, constraint_cost_drop_requires_validation, constraint_shadow_required, no_enabled_targets, firewall_blocked, other.

In addition to the standard headers, the response carries:

  • Content-Language: en or Content-Language: pt — the locale used to render explanation.text. Resolved from the request’s Accept-Language header, falling back to en on absent, malformed, or unsupported input. See Decision Explanation.
Statuserror codeWhen
400invalid_request_idrequest_id is not a valid UUID v4.
403read_permissionKey lacks read_permission.
403plan_requiredThe endpoint is not included on the caller’s plan.
404not_foundNo row exists in the caller’s organisation for that request_id. Returned with identical bytes for cross-tenant lookups so existence is not leaked.
410retention_expiredRow exists but is older than the plan’s log_retention_days. Body carries retention_window_days.
429rate_limitedExceeded 600 req/min/org or 200 req/min/key. Carries Retry-After.
5xxinternalUpstream analytics failure.
Terminal window
curl -s -H "Authorization: Bearer $FLOOPY_API_KEY" \
"https://api.floopy.ai/v1/decisions/0c4a1d3f-7bea-4a1f-8b6e-2c0a8e4d3f10"
  • 600 requests / minute / organization.
  • 200 requests / minute / API key.

Both windows are evaluated atomically; if either denies, the request is rejected with 429.