Create a gateway policy
Creates a gateway policy for the calling organization.
policy_type is one of spend_cap, default_spend_cap,
guard, or route_config. The shape of config depends on policy_type:
spend_cap/default_spend_cap:{"window": "hourly"|"daily"|"weekly"|"monthly", "limit_usd": <number>}guard:{"version": 1, "detect": {"pii": <bool>, "secrets": <bool>}, "timeout_seconds": <number>, "timeout_action": "allow"|"block"}timeout_seconds(optional, 0.1–30) caps guard pipeline execution time; defaults to 2s.timeout_actiondefaults toallow.route_config:{"strategy": "priority_fallback", "triggers": {"status_codes": [<int>]}, "fallbacks": [{"model_configs": [{"model_config_id": "<playground-settings-uuid>"}]}]}triggersis required, with no default:status_codesmust be a non-empty list (include 502 and 504 for upstream transport failures).fallbackscontains an entry whosemodel_configsare tried in priority order (1–5).subject_matchersmust be a singleworkspace_identry.
subject_matchers is a list of {key, value} pairs.
key is one of organization_id, workspace_id, user_id,
api_key_id, or run_rule_id. Multiple matchers AND together. A
default_spend_cap uses {key, value: ""} so the runtime
materializes a per-subject child for every distinct subject
of that kind it sees in request metadata.
action is currently always block. Spend caps reject the
request with 402 when the limit is hit; guard policies redact
matched content in-place before forwarding upstream.
Upsert by matchers: for spend_cap, default_spend_cap, and
guard, if a policy with the same subject_matchers already exists
in this organization, the existing policy is updated in place instead
of a duplicate being created. id is preserved. route_config does
not upsert by matchers — name must be unique per organization (409 on
conflict). Returns 201 either way.
Authorizations
Body
Response
Created
CurrentSpendUSD is the spend in the policy's current window. Set for any spend_cap policy regardless of enabled state — disabled policies still surface usage so users can see what would have been counted. Nil for non-spend_cap policies or when the spend lookup failed.
ParentPolicyID is set on materialized children of a default_spend_cap to the default's id, and cleared (NULL) only when an admin Create with the same matchers takes over the materialized row. Update on a child preserves the link; Delete on the parent cascade-soft-deletes every child rather than detaching them.

