Skip to content

GET /v1/optimization/verification

This endpoint answers one question on the caller’s own traffic, with their own numbers: does Floopy actually verify the savings story for this route, in the last 7 days? It is the API behind the dashboard’s Verification Status card on the Baseline-vs-Floopy page.

The answer is one of four states — verified, not_verified, insufficient_data, regression_detected — derived from a tenant-scoped aggregation over your request log, with the underlying baseline and floopy numbers returned alongside so you can audit the verdict.

GET https://api.floopy.ai/v1/optimization/verification?route_id=<uuid>&window=7d
Authorization: Bearer <your-floopy-api-key>
  • Permission: read_permission.
  • Available on all plans.
  • Our team is currently rolling this endpoint out gradually and validating data quality before broad availability — contact support for early access.
FieldTypeRequiredConstraints
route_idstring (UUID v4)YesThe id of the route whose performance you want to verify. Validated as a v4 UUID at the deserializer; malformed input returns 400 invalid_route_id.
windowstringYesClosed enum: 7d. v2 ships with a single fixed window; other windows are explicitly out of scope.

A successful call pre-fetches the route configuration scoped by the caller’s organization. If the route does not belong to the caller’s org, the response is 404 with bytes identical to a non-existent route; the analytics store is not queried.

{
"route_id": "5b3f9c1e-7a2b-4c3d-9e1f-0a1b2c3d4e5f",
"window": "7d",
"status": "verified",
"baseline": {
"samples": 4218,
"avg_cost_micro_usd": 412,
"composite_quality": 0.812,
"p50_latency_ms": 612
},
"floopy": {
"samples": 17392,
"avg_cost_micro_usd": 226,
"composite_quality": 0.804,
"p50_latency_ms": 588
},
"delta": {
"cost_pct": -45.1,
"quality_abs": -0.008,
"p50_latency_ms": -24
}
}
FieldTypeDescription
route_idUUIDEchoes the route_id query parameter.
windowstringEchoes the window query parameter (always 7d in v2).
statusstringClosed enum: verified, not_verified, insufficient_data, regression_detected. See Verification status methodology.
baseline.samplesintegerNumber of fallback (non-Floopy) requests on the route in the window. Counted from request-log rows where fallback_used = 1 and routing_rule_id = route_id.
baseline.avg_cost_micro_usdnumberMean cost_micro_usd over baseline.samples.
baseline.composite_qualitynumberMean composite quality score in [0.0, 1.0] over the same rows.
baseline.p50_latency_msnumberMedian end-to-end latency in milliseconds.
floopy.samplesintegerNumber of Floopy-routed requests on the route in the window. Counted where fallback_used = 0 and the routing strategy is one of the Floopy strategies (closed allowlist: feedback_driven, smart_cost, weighted, round_robin, latency_based).
floopy.avg_cost_micro_usdnumberMean cost over floopy.samples.
floopy.composite_qualitynumberMean composite quality in [0.0, 1.0].
floopy.p50_latency_msnumberMedian latency.
delta.cost_pctnumberPercentage change in cost: (floopy − baseline) / baseline * 100. Negative means Floopy is cheaper.
delta.quality_absnumberAbsolute change in composite quality: floopy − baseline. Negative means Floopy is lower-quality.
delta.p50_latency_msnumberAbsolute change in p50 latency in milliseconds.

When status == "insufficient_data", the baseline and floopy blocks are still populated with whatever was observed, but delta is omitted because the comparison is not meaningful below the sample floor.

When status == "regression_detected", the response is populated normally; the verdict is set by the bucketed regression signal from /v1/decisions over the same window, not by the cost/quality numbers in this response.

StatusWhen
verifiedBoth panels meet samples >= SAMPLE_FLOOR (100), no recent regressions on the route, and (baseline.composite_quality − floopy.composite_quality) <= QUALITY_TOLERANCE (0.03).
not_verifiedBoth panels meet the sample floor, no regressions, but Floopy quality is below baseline quality by more than QUALITY_TOLERANCE.
insufficient_dataEither panel has fewer than SAMPLE_FLOOR = 100 rows in the window. The honest answer when there is not enough traffic to make a verdict.
regression_detectedThe bucketed recent_regressions signal over the route is non-zero in the 7-day window. The endpoint refuses to call the route “verified” while a regression is in flight, regardless of the cost/quality numbers.

The constants are pinned in code (SAMPLE_FLOOR = 100, QUALITY_TOLERANCE = 0.03) and documented on Baseline-vs-Floopy methodology.

If any decision in the 7-day window has used_shared_pool_prior == true, the response includes the header:

Floopy-Aggregation-Notice: shared-pool-influenced

This tells you that cross-tenant priors influenced at least one decision feeding the verification verdict. The numbers are kept; the provenance is surfaced. See Confidence methodology for the underlying mechanism.

The endpoint Redis-caches the response per (organization_id, route_id, window) for 60 seconds. The Cache-Control: max-age=60 response header is echoed so HTTP intermediaries can honour the same TTL. Verification numbers shift slowly; the cache is sized for that cadence.

A cache hit returns the same payload byte-for-byte, including the Floopy-Aggregation-Notice header when applicable.

Statuserror codeWhen
400invalid_route_idroute_id is missing or not a valid UUID v4.
400invalid_windowwindow is missing or not in {7d}.
403read_permissionKey lacks read_permission.
403plan_requiredThe endpoint is not included on the caller’s plan.
404not_foundNo route exists in the caller’s org for that route_id. Bytes are identical to a cross-tenant lookup so existence is not leaked.
429rate_limitedExceeded 60 req/min/org or 20 req/min/key. Carries Retry-After.
503upstream_timeoutThe analytics aggregation exceeded the 5 s wall-clock timeout. Carries Retry-After: 60.
5xxinternalUpstream failure.
Terminal window
curl -s -H "Authorization: Bearer $FLOOPY_API_KEY" \
"https://api.floopy.ai/v1/optimization/verification?route_id=5b3f9c1e-7a2b-4c3d-9e1f-0a1b2c3d4e5f&window=7d" \
-i

The -i flag prints the response headers so you can see Cache-Control: max-age=60 and any Floopy-Aggregation-Notice.

  • 60 requests / minute / organization.
  • 20 requests / minute / API key.

Both windows are evaluated atomically. The lower per-key cap exists because verification numbers shift slowly — there is no signal to be had from polling at high cadence.

Every successful response writes an optimization.verification_read event to the audit log with:

  • actor_api_key_id — the API key id that called the endpoint.
  • resource_id — the route_id.
  • status — the closed-enum verification status (verified, not_verified, insufficient_data, regression_detected).

The event is throttled per (organization_id, key_id, route_id) for 60 seconds so a polling client does not flood the audit log.