Skip to content

Constraints API

The Constraints API is how a customer puts a leash on Floopy’s optimization. Two endpoints — GET to read the current set, PUT to replace it.

The semantics are full-replace: a missing key in PUT falls back to the platform default. There is no PATCH.

Authentication and gating (both endpoints)

Section titled “Authentication and gating (both endpoints)”
Authorization: Bearer <your-floopy-api-key>
  • Permission: read_permission for GET, write_permission for PUT.
  • Pro plan.
  • We are rolling this out per organization while we validate quality. Contact support if your organization is not yet enabled.

Read the current constraint set, with the platform defaults shown alongside.

GET https://api.floopy.ai/v1/constraints
{
"max_regression": { "value": 0.02, "window": "rolling_24h" },
"max_cost_increase": { "value": 0.05, "window": "rolling_24h" },
"confidence_threshold": 0.6,
"min_samples_before_promotion": 50,
"max_outcome_variance": 0.4,
"max_cost_drop_without_validation": 0.8,
"require_shadow_before_live": true,
"defaults": {
"max_regression": 0.05,
"max_cost_increase": 0.10,
"confidence_threshold": 0.0
}
}
FieldTypeDescription
max_regressionobject | nullCap on the rolling drop in composite quality vs. baseline. null means “use platform default”.
max_regression.valuenumber[0, 0.5]. The fractional drop ceiling (e.g. 0.02 = 2%).
max_regression.windowstringrolling_24h or rolling_7d.
max_cost_increaseobject | nullCap on the rolling cost increase vs. baseline. value [0, 5.0].
confidence_thresholdnumber | nullMinimum router confidence to route away from baseline, [0.0, 1.0]. null or 0.0 disables the gate. See Confidence methodology.
min_samples_before_promotioninteger | nullMinimum historical samples on a candidate before it can win. [1, 100_000]. null disables the gate.
max_outcome_variancenumber | nullMaximum rolling outcome variance the router will tolerate on a candidate. (0.0, 1.0]. null disables the gate.
max_cost_drop_without_validationnumber | nullMaximum fractional cost drop allowed without a passing shadow experiment in the staleness window. (0.0, 1.0]. null disables the gate.
require_shadow_before_liveboolean | nullWhen true, no candidate is promoted to live traffic on a route until that (provider, model) has at least one completed shadow experiment in the staleness window (default 30 days, configurable per workspace — contact support).
defaultsobjectPlatform defaults that fill in for any unset key.

The four new fields (min_samples_before_promotion, max_outcome_variance, max_cost_drop_without_validation, require_shadow_before_live) are documented end-to-end on the Constraints feature page.

StatusCodeWhen
403read_permission / plan_requiredPermission or plan flag missing.
5xxinternalUpstream failure.
Terminal window
curl -s -H "Authorization: Bearer $FLOOPY_API_KEY" \
"https://api.floopy.ai/v1/constraints" | jq .

Replace the constraint set. Body cap: 4 KiB.

PUT https://api.floopy.ai/v1/constraints
{
"max_regression": { "value": 0.02, "window": "rolling_24h" },
"max_cost_increase": { "value": 0.05, "window": "rolling_24h" },
"confidence_threshold": 0.7,
"min_samples_before_promotion": 50,
"max_outcome_variance": 0.4,
"max_cost_drop_without_validation": 0.8,
"require_shadow_before_live": true
}
FieldTypeRequiredConstraints
max_regressionobjectNovalue [0, 0.5], windowrolling_24h/rolling_7d. Omit to fall back to default 0.05.
max_cost_increaseobjectNovalue [0, 5.0], same window enum. Omit to fall back to default 0.10.
confidence_thresholdnumberNo[0.0, 1.0]. Omit to disable (0.0).
min_samples_before_promotionintegerNo[1, 100_000]. Setting 0 is rejected with 400 out_of_range_min_samples_before_promotion. Omit to disable.
max_outcome_variancenumberNo(0.0, 1.0], strict-greater-than-zero. is_finite() enforced. Omit to disable.
max_cost_drop_without_validationnumberNo(0.0, 1.0], strict-greater-than-zero. is_finite() enforced. Omit to disable.
require_shadow_before_livebooleanNoOmit or set false to disable.

The body is deny_unknown_fields — unknown keys return 400 unknown_field. Full-replace semantics: any key omitted from the PUT body is set to the platform default, not preserved. Every numeric field is is_finite() checked — NaN, +Inf, and -Inf are rejected with 400 out_of_range_<field>.

  • max_regression — when a candidate’s expected regression exceeds the cap, the candidate is filtered with reason: "constraint_max_regression".
  • max_cost_increase — when a candidate’s expected rolling cost increase exceeds the cap, the candidate is filtered with reason: "constraint_max_cost_increase".
  • confidence_threshold — when the router’s confidence is below the threshold, the strategy falls back to baseline and emits reason: "constraint_confidence_below_threshold" for every other candidate.
  • min_samples_before_promotion — a candidate with fewer than this many historical samples is filtered with reason: "constraint_min_samples".
  • max_outcome_variance — a candidate whose rolling outcome variance exceeds this cap is filtered with reason: "constraint_high_variance".
  • max_cost_drop_without_validation — a candidate whose expected fractional cost drop vs. baseline exceeds this cap is filtered with reason: "constraint_cost_drop_requires_validation" unless a passing shadow experiment exists in the staleness window.
  • require_shadow_before_live — when true, any candidate without a passing shadow experiment in the staleness window is filtered with reason: "constraint_shadow_required". The cache (constraint_shadow_pass:{org}:{provider}:{model}) is DEL-ed proactively on rollback so a recovery path runs hot.

Constraints compose. The router runs every gate on every candidate in this fixed order: max_cost_increase, max_regression, confidence_threshold, min_samples_before_promotion, max_outcome_variance, max_cost_drop_without_validation, require_shadow_before_live. The first rejection wins and is what the audit row shows.

Returns the post-write state, identical shape to GET.

StatusCodeWhen
400body_too_largeBody exceeds 4 KiB.
400unknown_fieldUnknown top-level key.
400out_of_range_<field>Field value outside the documented range.
403write_permission / plan_requiredPermission or plan flag missing.
5xxinternalUpstream failure.
Terminal window
curl -s -X PUT \
-H "Authorization: Bearer $FLOOPY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"max_regression": {"value": 0.02, "window": "rolling_24h"},
"max_cost_increase": {"value": 0.05, "window": "rolling_24h"},
"confidence_threshold": 0.6
}' \
"https://api.floopy.ai/v1/constraints"

Every successful PUT writes a row to constraint_changes with the before snapshot, the after snapshot, the actor_api_key_id, and the timestamp. The audit event metadata carries SHA-256 hashes of before and after so the audit log itself does not duplicate the raw constraint values.