Policy
Package: agentrouter.policy.v1 Service: PolicyService
Endpoints
Create a budget policy
Changed in v0.4.0 (bug fixes): CreateBudgetPolicy now accepts only the released TEAM, TEAM_PER_USER_DEFAULT, and API_KEY scopes. Existing policies in legacy scopes remain available for reads, updates, enforcement, and resolution.
Changed in v0.3.0 (behaviour changes): Per-key budget storage changes with migration 0131. If two per-key budgets were active on two keys of the same client at the same intent, the upgrade keeps the earliest and deactivates the rest, and the surviving limit now applies to the client's combined spend.
Changed in v0.3.0 (bug fixes): Creating, changing, deleting, or disabling a budget policy now schedules a gateway refresh for every project it governs. Previously only one project's gateways were refreshed, leaving other projects enforcing the old policy until the next periodic rebuild. Removing the last budget also clears older gateway snapshots that could otherwise keep blocking requests until another configuration refresh.
Changed in v0.3.0 (bug fixes): A budget policy on a single API key now caps the client behind the key, within the key's project, instead of the key row. Rotating the key used to strand the policy on the retired key, leaving the replacement with no budget while the policy still listed as active; the budget now follows the rotation, the period's spend is summed across every key of the client in that project, and both keys of a rotation pair are governed while both are live. The client is recorded on the policy when it is written, and at most one active per-key policy per project, client and intent is allowed (one default and one bound may coexist): creating, retargeting or activating a second one on another key of the same client, or attaching an already-budgeted key to such a client, is refused. A key cannot be moved out of a client that other keys stay in while that client's budget is active; deactivate the budget first. A per-key budget can only be created on, or retargeted to, a key that belongs to the project named in the request; a key in another project is reported as not found.
Changed in v0.3.0 (bug fixes): Budget policies with a block or fallback action are no longer accepted at the user and per-key-default team scopes, where enforcement does not evaluate them. Such a policy was stored and reported spend but never gated a request; creating one now returns an error naming the limitation, and monitor policies at these scopes remain supported. The few existing rows (internal testing only; the Console never authored these scopes) cannot be edited or re-activated while they keep the enforcing action; switching one to monitor or moving it to a scope enforcement governs unfreezes it, and deactivating or deleting it remains available either way.
What it does: Creates a new budget policy. For API_KEY scope, the named key's client and project are resolved under its row lock. Returns ABORTED if the key's project changed after authorization; a retry must still satisfy the request project's ownership check.
Request fields:
| Field | Required | Description |
|---|---|---|
budget_policy | yes | Required: policy to create. id must be absent or empty (server-assigned). |
customer_id | yes | Required: customer (tenant) that will own the created policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | yes | Required: project that will own the created policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
Response fields:
| Field | Required | Description |
|---|---|---|
budget_policy | no | The created policy with server-assigned fields populated. |
{"signatures":{"go":"c.Policy().CreateBudgetPolicy(ctx, \u0026policyv1.CreateBudgetPolicyRequest{...})","python":"client.policy.createbudgetpolicy(...)","typescript":"client.policy.createbudgetpolicy({...})","cli":"tare api policy budget-policies create --budget-policy $BUDGET_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"budget_policy\": {}\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy budget-policies create --budget-policy $BUDGET_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"budget_policy\": {}\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/budget-policies","slug":"create-a-budget-policy"}
Get a budget policy
Changed in v0.4.0 (new features): Budget policies can now report live billable spend and passthrough estimates, including per-member spend for teams and customer spend and near-limit, over-limit and unmeasured policy counts on list requests. Reads include target names, with user names and email addresses limited to the caller's directory permissions. Lists support target search and sorting, and inactive policies can be permanently removed. Statistics measure at most 500 active policies per request and indicate when more policies match. A failed measurement no longer discards the policy list; the response reports the number of failed measurements.
What it does: Returns a single budget policy by id.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to fetch. |
customer_id | no | Optional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
project_id | no | Optional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
include_spend | no | When true the returned policy carries spend, its current-period spend measured from the usage rollups (one rollup scan, plus the team roster for team scopes). Off by default so a plain read stays a single row lookup. |
Response fields:
| Field | Required | Description |
|---|---|---|
budget_policy | no | The requested policy. |
{"signatures":{"go":"c.Policy().GetBudgetPolicy(ctx, \u0026policyv1.GetBudgetPolicyRequest{...})","python":"client.policy.getbudgetpolicy(...)","typescript":"client.policy.getbudgetpolicy({...})","cli":"tare api policy budget-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy budget-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/budget-policies/{id}","slug":"get-a-budget-policy"}
List budget policies
Changed in v0.4.0 (behaviour changes): Listing budget policies now returns INVALID_ARGUMENT for a non-empty page.filter or an unsupported page.order_by, including multiple sort fields. These inputs were previously ignored.
Changed in v0.4.0 (new features): Budget policies can now report live billable spend and passthrough estimates, including per-member spend for teams and customer spend and near-limit, over-limit and unmeasured policy counts on list requests. Reads include target names, with user names and email addresses limited to the caller's directory permissions. Lists support target search and sorting, and inactive policies can be permanently removed. Statistics measure at most 500 active policies per request and indicate when more policies match. A failed measurement no longer discards the policy list; the response reports the number of failed measurements.
What it does: Returns budget policies matching the specified filters.
Request fields:
| Field | Required | Description |
|---|---|---|
page | no | Cursor-pagination inputs. order_by accepts a single field, one of name, spend_limit, created_at and updated_at, with an optional asc/ desc suffix (default name asc); any other field is INVALID_ARGUMENT. filter is declared on the shared message but not implemented here, and is rejected rather than ignored. The page token carries only the offset and does not bind it to order_by. Clear page_token when changing order_by to restart from the first page; reusing a token applies its old offset to the new order. |
search | no | Optional case-insensitive substring search on the policy name, the targeted team's name. The targeted user's name and email are also searched only within the permission and directory boundary used for returned identity fields. Applies to results, total and stats. % and _ match literally. |
scope_types | no | Filter to policies with these scope types. |
statuses | no | Filter to policies in these statuses. |
group_id | no | Filter to policies targeting this group_id. |
user_id | no | Filter to policies targeting this user_id. |
api_key_id | no | Filter to the policies that GOVERN this key -- those whose stored (client, project) is the key's effective client and project -- and only those. An api_key policy caps the key's client, so a key's budget may be a policy authored on the key it was rotated from, and a policy still naming a key that has since been attached to another client no longer governs it and is not listed for it. |
customer_id | no | Optional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
project_id | no | Optional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
include_spend | no | When true every returned policy carries spend (see BudgetPolicy.spend): one rollup scan per row, plus the team roster for team scopes. Lets a list page render live spend from one call instead of one read per row. A row whose measurement fails is still listed, without spend; the failure is logged server-side and a per-policy read can retry it. |
include_stats | no | When true the response carries stats: the near/over-limit split of the ACTIVE policies matching this request's filters. Measures at most 500 active policies in the requested sort order, independently of paging. stats.truncated signals a larger matching set. Individual measurement failures are counted in stats.measurement_failed_count; they do not discard the policy list or the other statistics. |
near_limit_threshold_pct | no | Percent of spend_limit at or above which an active policy counts towards stats.near_limit_count (1-100). Zero means the default, 80. |
include_customer_spend | no | When true the response carries customer_spend, the tenant's month-to-date spend. One rollup scan, independent of the policies listed, so a headline can be refreshed on its own clock without include_stats. |
Response fields:
| Field | Required | Description |
|---|---|---|
budget_policies | no | Policies matching the request filters, one page's worth. |
page | no | Cursor-pagination outputs. |
total | no | Total count of matching policies across all pages. |
stats | no | Near/over-limit split; present only when the request set include_stats. |
customer_spend | no | The tenant's spend in the current MONTHLY window across every api key it owns, whether or not any policy targets them; present only when the request set include_customer_spend. MEASURED, never summed from policy rows: project and system policies overlap the keys inside them, so their amounts are not additive. members is empty and available is true. |
{"signatures":{"go":"c.Policy().ListBudgetPolicies(ctx, \u0026policyv1.ListBudgetPoliciesRequest{...})","python":"client.policy.listbudgetpolicies(...)","typescript":"client.policy.listbudgetpolicies({...})","cli":"tare api policy budget-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy budget-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/budget-policies","slug":"list-budget-policies"}
Update a budget policy
Changed in v0.3.0 (behaviour changes): Per-key budget storage changes with migration 0131. If two per-key budgets were active on two keys of the same client at the same intent, the upgrade keeps the earliest and deactivates the rest, and the surviving limit now applies to the client's combined spend.
Changed in v0.3.0 (bug fixes): Creating, changing, deleting, or disabling a budget policy now schedules a gateway refresh for every project it governs. Previously only one project's gateways were refreshed, leaving other projects enforcing the old policy until the next periodic rebuild. Removing the last budget also clears older gateway snapshots that could otherwise keep blocking requests until another configuration refresh.
Changed in v0.3.0 (bug fixes): A budget policy on a single API key now caps the client behind the key, within the key's project, instead of the key row. Rotating the key used to strand the policy on the retired key, leaving the replacement with no budget while the policy still listed as active; the budget now follows the rotation, the period's spend is summed across every key of the client in that project, and both keys of a rotation pair are governed while both are live. The client is recorded on the policy when it is written, and at most one active per-key policy per project, client and intent is allowed (one default and one bound may coexist): creating, retargeting or activating a second one on another key of the same client, or attaching an already-budgeted key to such a client, is refused. A key cannot be moved out of a client that other keys stay in while that client's budget is active; deactivate the budget first. A per-key budget can only be created on, or retargeted to, a key that belongs to the project named in the request; a key in another project is reported as not found.
Changed in v0.3.0 (bug fixes): Budget policies with a block or fallback action are no longer accepted at the user and per-key-default team scopes, where enforcement does not evaluate them. Such a policy was stored and reported spend but never gated a request; creating one now returns an error naming the limitation, and monitor policies at these scopes remain supported. The few existing rows (internal testing only; the Console never authored these scopes) cannot be edited or re-activated while they keep the enforcing action; switching one to monitor or moving it to a scope enforcement governs unfreezes it, and deactivating or deleting it remains available either way.
Changed in v0.1.5 (bug fixes): Updating a budget policy, a rate-limit policy, or a user group with the all-zero UUID (00000000-0000-0000-0000-000000000000) now returns a 400 error that names the invalid field. These requests previously returned a 500 error.
What it does: Updates mutable budget policy fields. Omitted/empty scalar string fields leave the existing value untouched. Enum fields set to *_UNSPECIFIED leave the existing value untouched. The policy id must be set inside the budget_policy field. Restating the same api_key_id on an existing API_KEY policy preserves its stored client and project; supplying a different key retargets it. When a key target is supplied, returns ABORTED if its project changed after authorization. A retry must still satisfy the request project's ownership check.
Request fields:
| Field | Required | Description |
|---|---|---|
budget_policy | yes | Required: policy to update. budget_policy.id must be set. Partial update semantics: omitted/empty scalar string fields leave the existing value untouched; enum fields set to *_UNSPECIFIED leave the existing value untouched. |
customer_id | yes | Required: customer (tenant) that owns the target policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | yes | Required: project that owns the target policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
Response fields:
| Field | Required | Description |
|---|---|---|
budget_policy | no | The updated policy with server-assigned fields populated. |
{"signatures":{"go":"c.Policy().UpdateBudgetPolicy(ctx, \u0026policyv1.UpdateBudgetPolicyRequest{...})","python":"client.policy.updatebudgetpolicy(...)","typescript":"client.policy.updatebudgetpolicy({...})","cli":"tare api policy budget-policies update --budget-policy $BUDGET_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"budget_policy\": {}\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy budget-policies update --budget-policy $BUDGET_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"budget_policy\": {}\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/budget-policies/{budget_policy.id}","slug":"update-a-budget-policy"}
Delete a budget policy
Changed in v0.3.0 (bug fixes): Creating, changing, deleting, or disabling a budget policy now schedules a gateway refresh for every project it governs. Previously only one project's gateways were refreshed, leaving other projects enforcing the old policy until the next periodic rebuild. Removing the last budget also clears older gateway snapshots that could otherwise keep blocking requests until another configuration refresh.
What it does: Deactivates a budget policy (is_active = false); the row remains, still listed under statuses INACTIVE, and can be removed with PurgeBudgetPolicy once inactive.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to delete. |
customer_id | yes | Required: customer (tenant) that owns the target policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | yes | Required: project that owns the target policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
{"signatures":{"go":"c.Policy().DeleteBudgetPolicy(ctx, \u0026policyv1.DeleteBudgetPolicyRequest{...})","python":"client.policy.deletebudgetpolicy(...)","typescript":"client.policy.deletebudgetpolicy({...})","cli":"tare api policy budget-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy budget-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/budget-policies/{id}","slug":"delete-a-budget-policy"}
Set budget policy status
Changed in v0.3.0 (bug fixes): Creating, changing, deleting, or disabling a budget policy now schedules a gateway refresh for every project it governs. Previously only one project's gateways were refreshed, leaving other projects enforcing the old policy until the next periodic rebuild. Removing the last budget also clears older gateway snapshots that could otherwise keep blocking requests until another configuration refresh.
Changed in v0.3.0 (bug fixes): A budget policy on a single API key now caps the client behind the key, within the key's project, instead of the key row. Rotating the key used to strand the policy on the retired key, leaving the replacement with no budget while the policy still listed as active; the budget now follows the rotation, the period's spend is summed across every key of the client in that project, and both keys of a rotation pair are governed while both are live. The client is recorded on the policy when it is written, and at most one active per-key policy per project, client and intent is allowed (one default and one bound may coexist): creating, retargeting or activating a second one on another key of the same client, or attaching an already-budgeted key to such a client, is refused. A key cannot be moved out of a client that other keys stay in while that client's budget is active; deactivate the budget first. A per-key budget can only be created on, or retargeted to, a key that belongs to the project named in the request; a key in another project is reported as not found.
Changed in v0.3.0 (bug fixes): Budget policies with a block or fallback action are no longer accepted at the user and per-key-default team scopes, where enforcement does not evaluate them. Such a policy was stored and reported spend but never gated a request; creating one now returns an error naming the limitation, and monitor policies at these scopes remain supported. The few existing rows (internal testing only; the Console never authored these scopes) cannot be edited or re-activated while they keep the enforcing action; switching one to monitor or moving it to a scope enforcement governs unfreezes it, and deactivating or deleting it remains available either way.
What it does: Toggles a budget policy's active/inactive state (is_active). Activation retries concurrent changes to the policy's stored scope, client or project. Returns ABORTED if the target cannot be stabilized within the retry limit; the caller may retry.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to update. |
status | yes | Required: new operational status for the policy. |
customer_id | yes | Required: customer (tenant) that owns the target policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | yes | Required: project that owns the target policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
Response fields:
| Field | Required | Description |
|---|---|---|
budget_policy | no | The policy with the updated status. |
{"signatures":{"go":"c.Policy().SetBudgetPolicyStatus(ctx, \u0026policyv1.SetBudgetPolicyStatusRequest{...})","python":"client.policy.setbudgetpolicystatus(...)","typescript":"client.policy.setbudgetpolicystatus({...})","cli":"tare api policy budget-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H.../status\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"status\": \"...\"\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy budget-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H.../status\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"status\": \"...\"\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/budget-policies/{id}/status","slug":"set-budget-policy-status"}
Purge a budget policy
Changed in v0.4.0 (new features): Budget policies can now report live billable spend and passthrough estimates, including per-member spend for teams and customer spend and near-limit, over-limit and unmeasured policy counts on list requests. Reads include target names, with user names and email addresses limited to the caller's directory permissions. Lists support target search and sorting, and inactive policies can be permanently removed. Statistics measure at most 500 active policies per request and indicate when more policies match. A failed measurement no longer discards the policy list; the response reports the number of failed measurements.
Changed in v0.4.0 (new features): The API can now permanently remove an inactive budget policy without changing the existing deactivation behavior of DELETE. Without the admin scope, purge reaches only PROJECT and API_KEY policies in the request project. Callers with the admin scope can also purge inactive policies with other scopes in their customer.
What it does: Permanently removes an INACTIVE budget policy. DeleteBudgetPolicy only deactivates (budget_policies has no deleted_at column), so without this RPC an API-only operator could never remove a row. The policy must already be inactive -- deactivate it first through SetBudgetPolicyStatus or DeleteBudgetPolicy -- and that check is part of the delete statement itself, so a policy reactivated concurrently is left in place rather than destroyed. A caller without the admin scope may purge only PROJECT- and API_KEY-scoped policies within the request project. After request authorization, unknown policies and targets outside this allow-list both return NOT_FOUND. An active policy returns FAILED_PRECONDITION only if the caller is authorized to purge it. Alert history survives the purge with BudgetAlert.policy_id cleared (budget_alerts.policy_id is ON DELETE SET NULL), so ListBudgetAlerts can no longer find those alerts by policy_id.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the inactive policy to remove permanently. |
customer_id | yes | Required: customer (tenant) that owns the target policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | yes | Required: project context used to authorize this request. A caller without the admin scope may purge only PROJECT- or API_KEY-scoped policies whose project matches this value. After request authorization, other targets return NOT_FOUND. With the admin scope, the target may have another project or a tenant-wide scope. |
{"signatures":{"go":"c.Policy().PurgeBudgetPolicy(ctx, \u0026policyv1.PurgeBudgetPolicyRequest{...})","python":"client.policy.purgebudgetpolicy(...)","typescript":"client.policy.purgebudgetpolicy({...})","cli":"tare api policy budget-policies purge \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H.../purge\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{}'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy budget-policies purge \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/budget-policies/01H.../purge\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{}'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/budget-policies/{id}/purge","slug":"purge-a-budget-policy"}
List budget alerts
What it does: Returns system-fired budget alerts matching the specified filters.
Request fields:
| Field | Required | Description |
|---|---|---|
page | no | Cursor-pagination inputs. |
policy_id | no | Filter to alerts fired by this policy_id. |
group_id | no | Filter to alerts snapshotting this group_id. |
user_id | no | Filter to alerts snapshotting this user_id. |
api_key_id | no | Filter to alerts snapshotting this api_key_id. |
customer_id | no | Optional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
project_id | no | Optional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
Response fields:
| Field | Required | Description |
|---|---|---|
budget_alerts | no | Alerts matching the request filters, one page's worth. |
page | no | Cursor-pagination outputs. |
total | no | Total count of matching alerts across all pages. |
{"signatures":{"go":"c.Policy().ListBudgetAlerts(ctx, \u0026policyv1.ListBudgetAlertsRequest{...})","python":"client.policy.listbudgetalerts(...)","typescript":"client.policy.listbudgetalerts({...})","cli":"tare api policy budget-alerts list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-alerts\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy budget-alerts list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-alerts\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/budget-alerts","slug":"list-budget-alerts"}
Get a budget alert
What it does: Returns a single budget alert by id.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the alert to fetch. |
customer_id | no | Optional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
project_id | no | Optional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
Response fields:
| Field | Required | Description |
|---|---|---|
budget_alert | no | The requested alert. |
{"signatures":{"go":"c.Policy().GetBudgetAlert(ctx, \u0026policyv1.GetBudgetAlertRequest{...})","python":"client.policy.getbudgetalert(...)","typescript":"client.policy.getbudgetalert({...})","cli":"tare api policy budget-alerts get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-alerts/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy budget-alerts get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/budget-alerts/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/budget-alerts/{id}","slug":"get-a-budget-alert"}
Create a user group
What it does: Creates a new user group (team).
Request fields:
| Field | Required | Description |
|---|---|---|
user_group | yes | Required: group to create. id must be absent or empty (server-assigned). |
customer_id | yes | Required: customer (tenant) that will own the created group. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | yes | Required: project that will own the created group. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
Response fields:
| Field | Required | Description |
|---|---|---|
user_group | no | The created group with server-assigned fields populated. |
{"signatures":{"go":"c.Policy().CreateUserGroup(ctx, \u0026policyv1.CreateUserGroupRequest{...})","python":"client.policy.createusergroup(...)","typescript":"client.policy.createusergroup({...})","cli":"tare api policy user-groups create --user-group $USER_GROUP --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"user_group\": {}\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy user-groups create --user-group $USER_GROUP --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"user_group\": {}\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/user-groups","slug":"create-a-user-group"}
Get a user group
Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.
What it does: Returns a single user group by id.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the group to fetch. |
customer_id | no | Optional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
project_id | no | Optional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
Response fields:
| Field | Required | Description |
|---|---|---|
user_group | no | The requested group. |
{"signatures":{"go":"c.Policy().GetUserGroup(ctx, \u0026policyv1.GetUserGroupRequest{...})","python":"client.policy.getusergroup(...)","typescript":"client.policy.getusergroup({...})","cli":"tare api policy user-groups get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/user-groups/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy user-groups get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/user-groups/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/user-groups/{id}","slug":"get-a-user-group"}
List user groups
Changed in v0.5.0 (behaviour changes): ListUserGroups now returns InvalidArgument for a non-empty page.filter or an unsupported page.order_by instead of silently ignoring them.
Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.
What it does: Returns user groups matching the specified filters.
Request fields:
| Field | Required | Description |
|---|---|---|
page | no | Cursor-pagination inputs. page.order_by accepts a single field, one of name, member_count, created_at or updated_at, optionally followed by asc or desc (AIP-132). An empty order_by keeps the historical name asc. page.filter is not supported and is rejected rather than ignored. |
search | no | Optional case-insensitive substring search on group name or description. |
customer_id | no | Optional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
project_id | no | Optional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
has_members | no | When set, keeps only the teams that have members (true) or only the empty ones (false). Unset lists both. Optional because a plain bool cannot say "unset" apart from "false", and "only the empty teams" is a real query. |
include_stats | no | When true the response carries stats, the membership split over the same search. It is a second aggregate query, so it can see a slightly newer state than this page. Lets the list header render from one call instead of one page_size=1 query per aggregate. |
Response fields:
| Field | Required | Description |
|---|---|---|
user_groups | no | Groups matching the request filters, one page's worth. |
page | no | Cursor-pagination outputs. |
total | no | Total count of matching groups across all pages. Unlike stats, this honours the has_members filter -- it is the count this page is paging through. |
stats | no | Membership split; present only when the request set include_stats. |
{"signatures":{"go":"c.Policy().ListUserGroups(ctx, \u0026policyv1.ListUserGroupsRequest{...})","python":"client.policy.listusergroups(...)","typescript":"client.policy.listusergroups({...})","cli":"tare api policy user-groups list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/user-groups\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy user-groups list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/user-groups\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/user-groups","slug":"list-user-groups"}
Update a user group
Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.
Changed in v0.1.5 (bug fixes): Updating a budget policy, a rate-limit policy, or a user group with the all-zero UUID (00000000-0000-0000-0000-000000000000) now returns a 400 error that names the invalid field. These requests previously returned a 500 error.
What it does: Updates mutable user group fields. Omitted/empty scalar string fields leave the existing value untouched. The group id must be set inside the user_group field.
Request fields:
| Field | Required | Description |
|---|---|---|
user_group | yes | Required: group to update. user_group.id must be set. Partial update semantics: omitted/empty scalar string fields leave the existing value untouched. To remove a description rather than change it, see clear_description. |
customer_id | yes | Required: customer (tenant) that owns the target group. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | yes | Required: project that owns the target group. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
clear_description | no | When true, removes the group's description (fraser#8004). description is a plain proto3 string, so an empty user_group.description is indistinguishable on the wire from an omitted one -- both leave the existing description untouched, per the partial-update rule above. Declaring it optional string would carry presence instead, but changes the generated type of UserGroup.description for every reader; this flag adds the one missing intent without that churn. clear_description together with a non-empty user_group.description is rejected as INVALID_ARGUMENT: the two state opposite intents and there is no defensible winner. |
Response fields:
| Field | Required | Description |
|---|---|---|
user_group | no | The updated group with server-assigned fields populated. |
{"signatures":{"go":"c.Policy().UpdateUserGroup(ctx, \u0026policyv1.UpdateUserGroupRequest{...})","python":"client.policy.updateusergroup(...)","typescript":"client.policy.updateusergroup({...})","cli":"tare api policy user-groups update --user-group $USER_GROUP --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"user_group\": {},\n \"clear_description\": false\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy user-groups update --user-group $USER_GROUP --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"user_group\": {},\n \"clear_description\": false\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/user-groups/{user_group.id}","slug":"update-a-user-group"}
Delete a user group
Changed in v0.5.0 (behaviour changes): DeleteUserGroup now refuses with FailedPrecondition while the team still has members or is the target of an active budget policy. Previously, deleting a team with members failed with an internal error; deleting a team without members also deleted its budget policies.
What it does: Deletes a user group. The group must be empty and unreferenced: a group that still has members, or that an active budget policy targets, is refused with FAILED_PRECONDITION, so callers remove the members (RemoveUserGroupMembers) and deactivate the policies first. Inactive budget policies targeting the group are deleted with it.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the group to delete. |
customer_id | yes | Required: customer (tenant) that owns the target group. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | yes | Required: project that owns the target group. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
{"signatures":{"go":"c.Policy().DeleteUserGroup(ctx, \u0026policyv1.DeleteUserGroupRequest{...})","python":"client.policy.deleteusergroup(...)","typescript":"client.policy.deleteusergroup({...})","cli":"tare api policy user-groups delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy user-groups delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/user-groups/{id}","slug":"delete-a-user-group"}
List user group members
Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.
What it does: Returns the users who belong to a group, ordered by name.
Request fields:
| Field | Required | Description |
|---|---|---|
user_group_id | yes | Required: uuid of the group whose members to list. |
page | no | Cursor-pagination inputs. page.order_by accepts a single field, name or updated_at, optionally followed by asc or desc (AIP-132); empty keeps name asc. updated_at is the user row's last change, which AddUserGroupMembers writes, so updated_at desc approximates "recently added". page.filter is not supported and is rejected rather than ignored. |
customer_id | no | Optional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
project_id | no | Optional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
search | no | Optional case-insensitive substring match on the member's name, or email when the caller holds users_reader and the member is inside the caller's directory boundary. |
Response fields:
| Field | Required | Description |
|---|---|---|
members | no | The group's members, one page's worth, in the requested order. The directory fields follow the UserGroupMember rule: filled only for a caller holding users_reader and members inside that caller's directory boundary. |
page | no | Cursor-pagination outputs. |
total | no | Total members across all pages. |
{"signatures":{"go":"c.Policy().ListUserGroupMembers(ctx, \u0026policyv1.ListUserGroupMembersRequest{...})","python":"client.policy.listusergroupmembers(...)","typescript":"client.policy.listusergroupmembers({...})","cli":"tare api policy user-group-members list --user-group-id $USER_GROUP_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/user-groups/01H.../members\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy user-group-members list --user-group-id $USER_GROUP_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/user-groups/01H.../members\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/user-groups/{user_group_id}/members","slug":"list-user-group-members"}
Add user group members
Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.
What it does: Puts users into a group. A user already in another group is moved into this one, and the group they left comes back in moves -- the tag it overwrites is the only record of it. Ids that do not name a user are reported in failed; the rest of the batch still applies.
Request fields:
| Field | Required | Description |
|---|---|---|
user_group_id | yes | Required: uuid of the group to add to. |
user_ids | yes | Required: users to put into the group. Repeated ids are collapsed. |
customer_id | yes | Required: customer (tenant) that owns the target group. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | yes | Required: project that owns the target group. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
Response fields:
| Field | Required | Description |
|---|---|---|
added_user_ids | no | Users now in the group, including any that already were. |
failed | no | Ids the call could not add. Empty on a fully applied batch. |
moves | no | Users that were in another group before this call. |
{"signatures":{"go":"c.Policy().AddUserGroupMembers(ctx, \u0026policyv1.AddUserGroupMembersRequest{...})","python":"client.policy.addusergroupmembers(...)","typescript":"client.policy.addusergroupmembers({...})","cli":"tare api policy user-group-members add --user-group-id $USER_GROUP_ID --user-ids $USER_IDS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H.../members\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"user_ids\": []\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy user-group-members add --user-group-id $USER_GROUP_ID --user-ids $USER_IDS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H.../members\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"user_ids\": []\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/user-groups/{user_group_id}/members","slug":"add-user-group-members"}
Remove user group members
Changed in v0.5.0 (new features): Teams can now be managed end to end through PolicyService instead of the console's own database. AddUserGroupMembers and RemoveUserGroupMembers move users in and out of a team (a user already in another team of the same organization is moved, and the response names the team they left), ListUserGroupMembers pages a team's members with a name or email search and name or recently-added order, and every read of a team carries its member count and the first five members. ListUserGroups can filter by whether a team has members, search descriptions, sort by name, member count, created or updated time, and report how many teams have members. UpdateUserGroup can clear a description with clear_description. A member's email, avatar and ban flag are returned only to credentials that hold users_reader and only for members inside the caller's directory boundary; otherwise callers see ids and names. Email search follows the same scope and per-member boundary rules. Directory reads hide team IDs outside the caller's organization boundary; team filters and counts use the same visible membership.
What it does: Takes users out of a group. Removal is idempotent: a listed user who is not in the group is left alone rather than reported as an error.
Request fields:
| Field | Required | Description |
|---|---|---|
user_group_id | yes | Required: uuid of the group to remove from. |
user_ids | yes | Required: users to take out of the group. Repeated ids are collapsed. |
customer_id | yes | Required: customer (tenant) that owns the target group. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | yes | Required: project that owns the target group. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
Response fields:
| Field | Required | Description |
|---|---|---|
removed_user_ids | no | Users this call took out of the group. A listed user who was not in it is absent here, and is not an error. |
{"signatures":{"go":"c.Policy().RemoveUserGroupMembers(ctx, \u0026policyv1.RemoveUserGroupMembersRequest{...})","python":"client.policy.removeusergroupmembers(...)","typescript":"client.policy.removeusergroupmembers({...})","cli":"tare api policy user-group-members remove --user-group-id $USER_GROUP_ID --user-ids $USER_IDS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H.../members/remove\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"user_ids\": []\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy user-group-members remove --user-group-id $USER_GROUP_ID --user-ids $USER_IDS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/user-groups/01H.../members/remove\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"user_ids\": []\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/user-groups/{user_group_id}/members/remove","slug":"remove-user-group-members"}
Create a tag schema entry
What it does: Adds an allowed (tag_key, tag_value) pair to the tag catalog.
Request fields:
| Field | Required | Description |
|---|---|---|
tag_schema_entry | yes | Required: entry to create. id must be absent or empty (server-assigned). |
customer_id | yes | Required: customer (tenant) that will own the created entry. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | yes | Required: project that will own the created entry. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
Response fields:
| Field | Required | Description |
|---|---|---|
tag_schema_entry | no | The created entry with server-assigned fields populated. |
{"signatures":{"go":"c.Policy().CreateTagSchemaEntry(ctx, \u0026policyv1.CreateTagSchemaEntryRequest{...})","python":"client.policy.createtagschemaentry(...)","typescript":"client.policy.createtagschemaentry({...})","cli":"tare api policy tag-schema create --tag-schema-entry $TAG_SCHEMA_ENTRY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/tag-schema\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"tag_schema_entry\": {}\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy tag-schema create --tag-schema-entry $TAG_SCHEMA_ENTRY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/tag-schema\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"tag_schema_entry\": {}\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/tag-schema","slug":"create-a-tag-schema-entry"}
List tag schema entries
What it does: Returns allowed tag key/value pairs matching the specified filters.
Request fields:
| Field | Required | Description |
|---|---|---|
page | no | Cursor-pagination inputs. |
tag_key | no | Filter to entries with this tag_key. |
customer_id | no | Optional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
project_id | no | Optional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
Response fields:
| Field | Required | Description |
|---|---|---|
entries | no | Entries matching the request filters, one page's worth. |
page | no | Cursor-pagination outputs. |
total | no | Total count of matching entries across all pages. |
{"signatures":{"go":"c.Policy().ListTagSchema(ctx, \u0026policyv1.ListTagSchemaRequest{...})","python":"client.policy.listtagschema(...)","typescript":"client.policy.listtagschema({...})","cli":"tare api policy tag-schema list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/tag-schema\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy tag-schema list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/tag-schema\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/tag-schema","slug":"list-tag-schema-entries"}
Delete a tag schema entry
What it does: Removes an allowed (tag_key, tag_value) pair from the tag catalog.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the entry to delete. |
customer_id | yes | Required: customer (tenant) that owns the target entry. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | yes | Required: project that owns the target entry. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
{"signatures":{"go":"c.Policy().DeleteTagSchemaEntry(ctx, \u0026policyv1.DeleteTagSchemaEntryRequest{...})","python":"client.policy.deletetagschemaentry(...)","typescript":"client.policy.deletetagschemaentry({...})","cli":"tare api policy tag-schema delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/tag-schema/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy tag-schema delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/tag-schema/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/tag-schema/{id}","slug":"delete-a-tag-schema-entry"}
Add an API key tag
Changed in v0.1.5 (bug fixes): Changing an API key's policy tags, or enabling or disabling a key, now takes effect on the data plane promptly. Previously these changes only reached a project's gateways on the periodic resync, so a re-tagged key kept its old routing and fallback for up to ~30 minutes, a rate-limit change from a tag was not applied until an unrelated policy edit, and a disabled key kept serving until the resync.
Changed in v0.1.5 (bug fixes): The API key tag endpoints now answer 400 invalid_argument for the all-zero api key id, instead of 500. The all-zero uuid has valid syntax, so it passed every id guard and reached the database layer, where it became an internal error. List tags for a key, add a tag, remove a tag, and the policy coverage check all report the bad id the same way. Remove a tag answered 404 not found for this id before. It now answers 400 with the other three.
What it does: Attaches a (tag_key, tag_value) pair to an API key. Both must reference an existing TagSchemaEntry.
Request fields:
| Field | Required | Description |
|---|---|---|
api_key_id | yes | Required: owning api_keys.id. |
tag_key | yes | Required: tag key. Must reference an existing TagSchemaEntry. |
tag_value | yes | Required: tag value. Must reference an existing TagSchemaEntry for tag_key. |
customer_id | yes | Required: customer (tenant) that owns the target API key. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | yes | Required: project that owns the target API key. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
Response fields:
| Field | Required | Description |
|---|---|---|
api_key_tag | no | The created tag attachment. |
{"signatures":{"go":"c.Policy().AddApiKeyTag(ctx, \u0026policyv1.AddApiKeyTagRequest{...})","python":"client.policy.addapikeytag(...)","typescript":"client.policy.addapikeytag({...})","cli":"tare api policy api-key-tags add --api-key-id $API_KEY_ID --tag-key $TAG_KEY --tag-value $TAG_VALUE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/api-keys/01H.../tags\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"tag_key\": \"...\",\n \"tag_value\": \"...\"\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy api-key-tags add --api-key-id $API_KEY_ID --tag-key $TAG_KEY --tag-value $TAG_VALUE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/api-keys/01H.../tags\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"tag_key\": \"...\",\n \"tag_value\": \"...\"\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/api-keys/{api_key_id}/tags","slug":"add-an-api-key-tag"}
List API key tags
Changed in v0.1.5 (bug fixes): The API key tag endpoints now answer 400 invalid_argument for the all-zero api key id, instead of 500. The all-zero uuid has valid syntax, so it passed every id guard and reached the database layer, where it became an internal error. List tags for a key, add a tag, remove a tag, and the policy coverage check all report the bad id the same way. Remove a tag answered 404 not found for this id before. It now answers 400 with the other three.
What it does: Returns tags attached to an API key.
Request fields:
| Field | Required | Description |
|---|---|---|
api_key_id | yes | Required: owning api_keys.id. |
page | no | Cursor-pagination inputs. |
customer_id | no | Optional: customer (tenant) scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
project_id | no | Optional: project scope for future project-scoped filtering. Not currently enforced -- reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
Response fields:
| Field | Required | Description |
|---|---|---|
api_key_tags | no | Tags attached to the requested API key, one page's worth. |
page | no | Cursor-pagination outputs. |
total | no | Total count of matching tags across all pages. |
{"signatures":{"go":"c.Policy().ListApiKeyTags(ctx, \u0026policyv1.ListApiKeyTagsRequest{...})","python":"client.policy.listapikeytags(...)","typescript":"client.policy.listapikeytags({...})","cli":"tare api policy api-key-tags list --api-key-id $API_KEY_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/api-keys/01H.../tags\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy api-key-tags list --api-key-id $API_KEY_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/api-keys/01H.../tags\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/api-keys/{api_key_id}/tags","slug":"list-api-key-tags"}
Remove an API key tag
Changed in v0.1.5 (bug fixes): Changing an API key's policy tags, or enabling or disabling a key, now takes effect on the data plane promptly. Previously these changes only reached a project's gateways on the periodic resync, so a re-tagged key kept its old routing and fallback for up to ~30 minutes, a rate-limit change from a tag was not applied until an unrelated policy edit, and a disabled key kept serving until the resync.
Changed in v0.1.5 (bug fixes): The API key tag endpoints now answer 400 invalid_argument for the all-zero api key id, instead of 500. The all-zero uuid has valid syntax, so it passed every id guard and reached the database layer, where it became an internal error. List tags for a key, add a tag, remove a tag, and the policy coverage check all report the bad id the same way. Remove a tag answered 404 not found for this id before. It now answers 400 with the other three.
What it does: Detaches a tag from an API key.
Request fields:
| Field | Required | Description |
|---|---|---|
api_key_id | yes | Required: owning api_keys.id. |
id | yes | Required: uuid of the tag attachment to remove. |
customer_id | yes | Required: customer (tenant) that owns the target API key. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | yes | Required: project that owns the target API key. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
{"signatures":{"go":"c.Policy().RemoveApiKeyTag(ctx, \u0026policyv1.RemoveApiKeyTagRequest{...})","python":"client.policy.removeapikeytag(...)","typescript":"client.policy.removeapikeytag({...})","cli":"tare api policy api-key-tags remove --api-key-id $API_KEY_ID \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/api-keys/01H.../tags/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy api-key-tags remove --api-key-id $API_KEY_ID \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/api-keys/01H.../tags/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/api-keys/{api_key_id}/tags/{id}","slug":"remove-an-api-key-tag"}
Get the effective policy for a scope
Changed in v0.5.0 (new features): PolicyService can explain which attribute-routing policy governs a key or tag preview. It returns the enabled winner, ordered rules and precedence details, and reports how many eligible keys are covered. These views require the attribute_routing_policies.read permission.
What it does: Resolves every BudgetPolicy applicable to a scope-target tuple down to the single clamp-winning policy.
Request fields:
| Field | Required | Description |
|---|---|---|
scope_type | yes | Required: scope type of the target to resolve. |
group_id | no | Team target. Set when scope_type targets a group (see PolicyScopeType). |
user_id | no | User target. Set when scope_type = POLICY_SCOPE_TYPE_USER. |
api_key_id | no | API key target. Set when scope_type = POLICY_SCOPE_TYPE_API_KEY, or to resolve an API_KEY_TAG match against that key's attached tags. |
tags | no | Tag key/value selector. Set when scope_type = POLICY_SCOPE_TYPE_API_KEY_TAG and api_key_id is not supplied. |
customer_id | no | Optional: customer (tenant) scope. Merged with the caller's authenticated claims (resolvePolicyCustomerID); reads remain scopes:["policy_reader"]; see the file-level PROJECT SCOPING note. |
project_id | no | Optional and, for scope_type = API_KEY, IGNORED: the server derives the key's project scope itself from the api_keys row identified by api_key_id (resolveApiKeyScope), the same way the dataplane's runtime policy resolvers scope a key's policies -- a caller-supplied project_id is never trusted for resolution. Only consulted for scope_type = API_KEY_TAG, where there is no api_key_id to derive it from. |
view | no | Optional family view. Unknown values are rejected. The attribute-routing view uses only key and tag-preview targets and returns no legacy families. |
Response fields:
| Field | Required | Description |
|---|---|---|
effective_policy | no | The resolved effective policy for the requested scope-target tuple. |
{"signatures":{"go":"c.Policy().GetEffectivePolicy(ctx, \u0026policyv1.GetEffectivePolicyRequest{...})","python":"client.policy.geteffectivepolicy(...)","typescript":"client.policy.geteffectivepolicy({...})","cli":"tare api policy effective --scope-type $SCOPE_TYPE","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/effective-policy\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy effective --scope-type $SCOPE_TYPE","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/effective-policy\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/effective-policy","slug":"get-the-effective-policy-for-a-scope"}
Get policy coverage for a scope
Changed in v0.5.0 (new features): PolicyService can explain which attribute-routing policy governs a key or tag preview. It returns the enabled winner, ordered rules and precedence details, and reports how many eligible keys are covered. These views require the attribute_routing_policies.read permission.
Changed in v0.1.5 (bug fixes): The API key tag endpoints now answer 400 invalid_argument for the all-zero api key id, instead of 500. The all-zero uuid has valid syntax, so it passed every id guard and reached the database layer, where it became an internal error. List tags for a key, add a tag, remove a tag, and the policy coverage check all report the bad id the same way. Remove a tag answered 404 not found for this id before. It now answers 400 with the other three.
What it does: Reports whether a scope reference has at least one applicable BudgetPolicy, and lists which ones apply.
Request fields:
| Field | Required | Description |
|---|---|---|
scope_type | no | Required for legacy selector coverage; must be unspecified for policy-ID coverage. |
group_id | no | Team target. Set when scope_type targets a group (see PolicyScopeType). |
user_id | no | User target. Set when scope_type = POLICY_SCOPE_TYPE_USER. |
api_key_id | no | API key target. Set when scope_type = POLICY_SCOPE_TYPE_API_KEY, or to check coverage for an API_KEY_TAG match against that key's attached tags. |
tags | no | Tag key/value selector. Set when scope_type = POLICY_SCOPE_TYPE_API_KEY_TAG and api_key_id is not supplied. |
customer_id | no | Optional tenant context, checked against the authenticated caller. |
project_id | no | Optional project context. For policy-ID coverage it must match the stored project boundary; it cannot narrow an organization-wide count. |
attribute_routing_policy_id | no | Optional attribute-routing policy ID. Requires attribute_routing_policies.read at the stored policy target; organization/tag counts require organization reach. scope_type must be unspecified and group_id/user_id/api_key_id/tags absent. Tenant/project hints cannot change the stored target; conflicting hints fail. Without this field, legacy selector behavior is unchanged. |
Response fields:
| Field | Required | Description |
|---|---|---|
coverage | no | Coverage result for the requested scope reference. |
attribute_routing_coverage | no | Only present for attribute_routing_policy_id requests; coverage is absent. |
{"signatures":{"go":"c.Policy().GetPolicyCoverage(ctx, \u0026policyv1.GetPolicyCoverageRequest{...})","python":"client.policy.getpolicycoverage(...)","typescript":"client.policy.getpolicycoverage({...})","cli":"tare api policy coverage","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/coverage\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy coverage","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/coverage\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/coverage","slug":"get-policy-coverage-for-a-scope"}
Create a rate-limit policy
What it does: Creates a new rate-limit policy.
Request fields:
| Field | Required | Description |
|---|---|---|
rate_limit_policy | yes | Required: policy to create. id must be absent or empty (server-assigned). |
customer_id | yes | Required: customer (tenant) that will own the created policy. Read by the project_owner persona to authorize the caller. |
project_id | yes | Required: project that will own the created policy. Read by the project_owner persona to authorize the caller. |
Response fields:
| Field | Required | Description |
|---|---|---|
rate_limit_policy | no | The created policy with server-assigned fields populated. |
{"signatures":{"go":"c.Policy().CreateRateLimitPolicy(ctx, \u0026policyv1.CreateRateLimitPolicyRequest{...})","python":"client.policy.createratelimitpolicy(...)","typescript":"client.policy.createratelimitpolicy({...})","cli":"tare api policy rate-limit-policies create --rate-limit-policy $RATE_LIMIT_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"rate_limit_policy\": {}\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy rate-limit-policies create --rate-limit-policy $RATE_LIMIT_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"rate_limit_policy\": {}\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/rate-limit-policies","slug":"create-a-rate-limit-policy"}
Get a rate-limit policy
What it does: Returns a single rate-limit policy by id.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to fetch. |
customer_id | no | Optional: customer (tenant) scope. Not currently enforced -- reads remain scopes:["policy_reader"]. |
project_id | no | Optional: project scope. Not currently enforced -- reads remain scopes:["policy_reader"]. |
Response fields:
| Field | Required | Description |
|---|---|---|
rate_limit_policy | no | The requested policy. |
{"signatures":{"go":"c.Policy().GetRateLimitPolicy(ctx, \u0026policyv1.GetRateLimitPolicyRequest{...})","python":"client.policy.getratelimitpolicy(...)","typescript":"client.policy.getratelimitpolicy({...})","cli":"tare api policy rate-limit-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/rate-limit-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy rate-limit-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/rate-limit-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/rate-limit-policies/{id}","slug":"get-a-rate-limit-policy"}
List rate-limit policies
What it does: Returns rate-limit policies matching the specified filters.
Request fields:
| Field | Required | Description |
|---|---|---|
page | no | Cursor-pagination inputs. |
search | no | Optional substring search on policy name. |
scope_types | no | Filter to policies with these scope types. |
statuses | no | Filter to policies in these statuses. |
api_key_id | no | Filter to policies targeting this api_key_id. |
customer_id | no | Optional: customer (tenant) scope. Not currently enforced -- reads remain scopes:["policy_reader"]. |
project_id | no | Optional: project scope. Not currently enforced -- reads remain scopes:["policy_reader"]. |
Response fields:
| Field | Required | Description |
|---|---|---|
rate_limit_policies | no | Policies matching the request filters, one page's worth. |
page | no | Cursor-pagination outputs. |
total | no | Total count of matching policies across all pages. |
{"signatures":{"go":"c.Policy().ListRateLimitPolicies(ctx, \u0026policyv1.ListRateLimitPoliciesRequest{...})","python":"client.policy.listratelimitpolicies(...)","typescript":"client.policy.listratelimitpolicies({...})","cli":"tare api policy rate-limit-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/rate-limit-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy rate-limit-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/rate-limit-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/rate-limit-policies","slug":"list-rate-limit-policies"}
Upsert a fallback policy
Changed in v0.5.0 (new features): Fallback policies can now define independent ordered fallback entries for each model, so requests fail over through the configured providers in the order specified. UpsertFallbackPolicy replaces the full set of entries for an organization, project, or API-key target in one idempotent call: omitted models are removed and an empty set deactivates the target. Existing policy clients using the flat chain representation remain compatible.
Changed in v0.5.0 (bug fixes): Fallback policies now keep independent ordered entries for each protected model and resolve project and organization policies, plus API-key policies, in the documented precedence order. Full-set updates converge on replay, remove omitted entries, and treat an explicit empty set as a deactivated override while preserving legacy fallback-chain aliases.
What it does: Replaces the complete set of fallback entries for one organization, project, or API-key target. entries is authoritative: omitted protected models are removed, and an empty set deactivates the target. Release 1 precedence is API key > project > organization/customer; tag targets are reporting-only and cannot be created by this operation. Eligible retry categories are timeout, rate-limit/capacity, and server error. Malformed requests, content refusals, rejected credentials, and other non-eligible client failures do not advance the ordered list. Effective responses and request logs identify the serving model and the source scope/policy. The public names are FallbackPolicy, fallback-policies, entries, and fallback_models; FallbackChainPolicy and chain remain read/write aliases for legacy clients.
Request fields:
| Field | Required | Description |
|---|---|---|
fallback_policy | yes | Complete desired policy state for the target. |
customer_id | yes | Fraser organization/tenant that owns the target. |
project_id | no | Required only for PROJECT scope. |
Response fields:
| Field | Required | Description |
|---|---|---|
fallback_policy | no | The committed canonical policy, including the complete grouped entry set. |
{"signatures":{"go":"c.Policy().UpsertFallbackPolicy(ctx, \u0026policyv1.UpsertFallbackPolicyRequest{...})","python":"client.policy.upsertfallbackpolicy(...)","typescript":"client.policy.upsertfallbackpolicy({...})","cli":"tare api policy fallback-policies upsert --fallback-policy $FALLBACK_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-policies:upsert\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"fallback_policy\": {}\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy fallback-policies upsert --fallback-policy $FALLBACK_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-policies:upsert\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"fallback_policy\": {}\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/fallback-policies:upsert","slug":"upsert-a-fallback-policy"}
Create a fallback chain policy
Changed in v0.5.0 (new features): Fallback policies can now define independent ordered fallback entries for each model, so requests fail over through the configured providers in the order specified. UpsertFallbackPolicy replaces the full set of entries for an organization, project, or API-key target in one idempotent call: omitted models are removed and an empty set deactivates the target. Existing policy clients using the flat chain representation remain compatible.
Request fields:
| Field | Required | Description |
|---|---|---|
fallback_chain_policy | yes | Required: policy to create. id must be absent or empty (server-assigned). |
customer_id | yes | Required: customer (tenant) that will own the created policy. Read by the project_owner persona to authorize the caller; see the file-level PROJECT SCOPING note. |
project_id | no | Required only for PROJECT scope. Omit for CUSTOMER and API_KEY scope; the server validates the target's tenant ownership. |
Response fields:
| Field | Required | Description |
|---|---|---|
fallback_chain_policy | no | The created policy with server-assigned fields populated. |
{"signatures":{"go":"c.Policy().CreateFallbackChainPolicy(ctx, \u0026policyv1.CreateFallbackChainPolicyRequest{...})","python":"client.policy.createfallbackchainpolicy(...)","typescript":"client.policy.createfallbackchainpolicy({...})","cli":"tare api policy fallback-chain-policies create --fallback-chain-policy $FALLBACK_CHAIN_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"fallback_chain_policy\": {}\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy fallback-chain-policies create --fallback-chain-policy $FALLBACK_CHAIN_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"fallback_chain_policy\": {}\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/fallback-chain-policies","slug":"create-a-fallback-chain-policy"}
Get a fallback chain policy
Changed in v0.5.0 (new features): Fallback policies can now define independent ordered fallback entries for each model, so requests fail over through the configured providers in the order specified. UpsertFallbackPolicy replaces the full set of entries for an organization, project, or API-key target in one idempotent call: omitted models are removed and an empty set deactivates the target. Existing policy clients using the flat chain representation remain compatible.
What it does: Returns a single fallback chain policy by id.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to fetch. |
customer_id | no | Optional: customer (tenant) scope for future project-scoped filtering. |
project_id | no | Optional: project scope for future project-scoped filtering. |
Response fields:
| Field | Required | Description |
|---|---|---|
fallback_chain_policy | no | The requested policy. |
{"signatures":{"go":"c.Policy().GetFallbackChainPolicy(ctx, \u0026policyv1.GetFallbackChainPolicyRequest{...})","python":"client.policy.getfallbackchainpolicy(...)","typescript":"client.policy.getfallbackchainpolicy({...})","cli":"tare api policy fallback-chain-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/fallback-chain-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy fallback-chain-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/fallback-chain-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/fallback-chain-policies/{id}","slug":"get-a-fallback-chain-policy"}
List fallback chain policies
What it does: Returns fallback chain policies matching the specified filters.
Request fields:
| Field | Required | Description |
|---|---|---|
page | no | Cursor-pagination inputs. |
target_scope_types | no | Filter to policies with these target scope types. |
statuses | no | Filter to policies in these statuses. |
target_key_id | no | Filter to policies targeting this target_key_id. |
target_project_id | no | Filter to policies targeting this target_project_id. |
customer_id | no | Optional: customer (tenant) scope for future project-scoped filtering. |
project_id | no | Optional: project scope for future project-scoped filtering. |
Response fields:
| Field | Required | Description |
|---|---|---|
fallback_chain_policies | no | Policies matching the request filters, one page's worth. |
page | no | Cursor-pagination outputs. |
total | no | Total count of matching policies across all pages. |
{"signatures":{"go":"c.Policy().ListFallbackChainPolicies(ctx, \u0026policyv1.ListFallbackChainPoliciesRequest{...})","python":"client.policy.listfallbackchainpolicies(...)","typescript":"client.policy.listfallbackchainpolicies({...})","cli":"tare api policy fallback-chain-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/fallback-chain-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy fallback-chain-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/fallback-chain-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/fallback-chain-policies","slug":"list-fallback-chain-policies"}
Update a rate-limit policy
Changed in v0.1.5 (bug fixes): Updating a budget policy, a rate-limit policy, or a user group with the all-zero UUID (00000000-0000-0000-0000-000000000000) now returns a 400 error that names the invalid field. These requests previously returned a 500 error.
What it does: Updates mutable rate-limit policy fields. Omitted/empty scalar fields leave the existing value untouched. Enum fields set to *_UNSPECIFIED leave the existing value untouched. The policy id must be set inside the rate_limit_policy field.
Request fields:
| Field | Required | Description |
|---|---|---|
rate_limit_policy | yes | Required: policy to update. rate_limit_policy.id must be set. Partial update semantics: omitted/empty scalar fields leave the existing value untouched; enum fields set to *_UNSPECIFIED leave the existing value untouched. |
customer_id | yes | Required: customer (tenant) that owns the target policy. Read by the project_owner persona to authorize the caller. |
project_id | yes | Required: project that owns the target policy. Read by the project_owner persona to authorize the caller. |
Response fields:
| Field | Required | Description |
|---|---|---|
rate_limit_policy | no | The updated policy with server-assigned fields populated. |
{"signatures":{"go":"c.Policy().UpdateRateLimitPolicy(ctx, \u0026policyv1.UpdateRateLimitPolicyRequest{...})","python":"client.policy.updateratelimitpolicy(...)","typescript":"client.policy.updateratelimitpolicy({...})","cli":"tare api policy rate-limit-policies update --rate-limit-policy $RATE_LIMIT_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"rate_limit_policy\": {}\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy rate-limit-policies update --rate-limit-policy $RATE_LIMIT_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"rate_limit_policy\": {}\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/rate-limit-policies/{rate_limit_policy.id}","slug":"update-a-rate-limit-policy"}
Update a fallback chain policy
Changed in v0.5.0 (new features): Fallback policies can now define independent ordered fallback entries for each model, so requests fail over through the configured providers in the order specified. UpsertFallbackPolicy replaces the full set of entries for an organization, project, or API-key target in one idempotent call: omitted models are removed and an empty set deactivates the target. Existing policy clients using the flat chain representation remain compatible.
What it does: Updates mutable fallback chain policy fields. Omitted/empty scalar string fields leave the existing value untouched. The policy id must be set inside the fallback_chain_policy field.
Request fields:
| Field | Required | Description |
|---|---|---|
fallback_chain_policy | yes | Required: policy to update. fallback_chain_policy.id must be set. Partial update semantics: omitted/empty scalar string fields leave the existing value untouched. Enum fields set to *_UNSPECIFIED leave the existing value untouched. |
customer_id | yes | Required: customer (tenant) that owns the target policy. |
project_id | no | Required only for the legacy PROJECT route. Omit for CUSTOMER and API_KEY scope. |
Response fields:
| Field | Required | Description |
|---|---|---|
fallback_chain_policy | no | The updated policy with server-assigned fields populated. |
{"signatures":{"go":"c.Policy().UpdateFallbackChainPolicy(ctx, \u0026policyv1.UpdateFallbackChainPolicyRequest{...})","python":"client.policy.updatefallbackchainpolicy(...)","typescript":"client.policy.updatefallbackchainpolicy({...})","cli":"tare api policy fallback-chain-policies update --fallback-chain-policy $FALLBACK_CHAIN_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"fallback_chain_policy\": {}\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy fallback-chain-policies update --fallback-chain-policy $FALLBACK_CHAIN_POLICY --customer-id $CUSTOMER_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"fallback_chain_policy\": {}\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/fallback-chain-policies/{fallback_chain_policy.id}","slug":"update-a-fallback-chain-policy"}
Delete a rate-limit policy
What it does: Deletes a rate-limit policy.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to delete. |
customer_id | yes | Required: customer (tenant) that owns the target policy. Read by the project_owner persona to authorize the caller. |
project_id | yes | Required: project that owns the target policy. Read by the project_owner persona to authorize the caller. |
{"signatures":{"go":"c.Policy().DeleteRateLimitPolicy(ctx, \u0026policyv1.DeleteRateLimitPolicyRequest{...})","python":"client.policy.deleteratelimitpolicy(...)","typescript":"client.policy.deleteratelimitpolicy({...})","cli":"tare api policy rate-limit-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy rate-limit-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/rate-limit-policies/{id}","slug":"delete-a-rate-limit-policy"}
Delete a fallback chain policy
What it does: Deletes a fallback chain policy.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to delete. |
customer_id | yes | Required: customer (tenant) that owns the target policy. |
project_id | no | Required only for the legacy PROJECT route. Omit for CUSTOMER and API_KEY scope. |
target_key_id | no | Required only by the API_KEY route; used to identify the affected key. |
{"signatures":{"go":"c.Policy().DeleteFallbackChainPolicy(ctx, \u0026policyv1.DeleteFallbackChainPolicyRequest{...})","python":"client.policy.deletefallbackchainpolicy(...)","typescript":"client.policy.deletefallbackchainpolicy({...})","cli":"tare api policy fallback-chain-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy fallback-chain-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/fallback-chain-policies/{id}","slug":"delete-a-fallback-chain-policy"}
Set rate-limit policy status
What it does: Toggles a rate-limit policy's active/inactive state (is_active).
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to update. |
status | yes | Required: new operational status for the policy. |
customer_id | yes | Required: customer (tenant) that owns the target policy. Read by the project_owner persona to authorize the caller. |
project_id | yes | Required: project that owns the target policy. Read by the project_owner persona to authorize the caller. |
Response fields:
| Field | Required | Description |
|---|---|---|
rate_limit_policy | no | The policy with the updated status. |
{"signatures":{"go":"c.Policy().SetRateLimitPolicyStatus(ctx, \u0026policyv1.SetRateLimitPolicyStatusRequest{...})","python":"client.policy.setratelimitpolicystatus(...)","typescript":"client.policy.setratelimitpolicystatus({...})","cli":"tare api policy rate-limit-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies/01H.../status\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"status\": \"...\"\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy rate-limit-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/rate-limit-policies/01H.../status\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"status\": \"...\"\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/rate-limit-policies/{id}/status","slug":"set-rate-limit-policy-status"}
Set fallback chain policy status
What it does: Toggles a fallback chain policy's active/inactive state (is_active).
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to update. |
status | yes | Required: new operational status for the policy. |
customer_id | yes | Required: customer (tenant) that owns the target policy. |
project_id | no | Required only for the legacy PROJECT route. Omit for CUSTOMER and API_KEY scope. |
target_key_id | no | Required only by the API_KEY route; used to identify the affected key. |
Response fields:
| Field | Required | Description |
|---|---|---|
fallback_chain_policy | no | The policy with the updated status. |
{"signatures":{"go":"c.Policy().SetFallbackChainPolicyStatus(ctx, \u0026policyv1.SetFallbackChainPolicyStatusRequest{...})","python":"client.policy.setfallbackchainpolicystatus(...)","typescript":"client.policy.setfallbackchainpolicystatus({...})","cli":"tare api policy fallback-chain-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies/01H.../status\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"status\": \"...\",\n \"target_key_id\": \"...\"\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy fallback-chain-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/fallback-chain-policies/01H.../status\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"status\": \"...\",\n \"target_key_id\": \"...\"\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/fallback-chain-policies/{id}/status","slug":"set-fallback-chain-policy-status"}
Get would-have-limited analytics for a rate-limit policy
What it does: Computes a "would-have-limited" analytics preview for a MONITOR-action rate-limit policy (fraser#5446 pass 2, item 4.4 / ADR-036 R2 Option B): for each hour in the lookback window, it sums the policy's audience (the same scope resolution the min-clamp resolver uses -- key / tag / project / system) from the existing usage rollups (usage_hourly_rollups) and reports how many of those hours would have breached the policy's triplet ceiling, had the policy been enforced. This is NOT true shadow-mode enforcement (no per-request evaluation, no sub-hour granularity) -- it is a rollup-derived retrospective estimate, intended to help an operator decide whether flipping a MONITOR policy to BLOCK is safe (see the Flow-1 monitor->active flip, fraser#5448). Rejects a BLOCK-action policy's id with FailedPrecondition: a BLOCK policy is already actually enforced by the min-clamp resolver, so a retrospective "would it have limited" estimate is not meaningful for it.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the (MONITOR-action) rate-limit policy to evaluate. |
customer_id | no | Optional: customer (tenant) scope. Not currently enforced -- reads remain scopes:["policy_reader"]. |
project_id | no | Optional: project scope. Not currently enforced -- reads remain scopes:["policy_reader"]. |
lookback_hours | no | Optional: lookback window in hours, ending now. Defaults to 72 hours server-side when unset or 0; clamped to the usage_hourly_rollups retention window (rollups older than retention have already been deleted, so a larger request silently evaluates fewer hours than asked). |
Response fields:
| Field | Required | Description |
|---|---|---|
analytics | no | undocumented |
{"signatures":{"go":"c.Policy().GetRateLimitPolicyAnalytics(ctx, \u0026policyv1.GetRateLimitPolicyAnalyticsRequest{...})","python":"client.policy.getratelimitpolicyanalytics(...)","typescript":"client.policy.getratelimitpolicyanalytics({...})","cli":"tare api policy rate-limit-policies analytics \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/rate-limit-policies/01H.../analytics\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy rate-limit-policies analytics \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/rate-limit-policies/01H.../analytics\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/rate-limit-policies/{id}/analytics","slug":"get-would-have-limited-analytics-for-a-rate-limit-policy"}
Create a traffic split policy
What it does: Creates a new traffic-split policy scoped to a key, tag selector, or project (fraser#5447, item 4.2).
Request fields:
| Field | Required | Description |
|---|---|---|
traffic_split_policy | yes | Required: policy to create. id must be absent or empty (server-assigned). |
customer_id | yes | Required: customer (tenant) that will own the created policy. |
project_id | yes | Required: project that will own the created policy. |
Response fields:
| Field | Required | Description |
|---|---|---|
traffic_split_policy | no | The created policy with server-assigned fields populated. |
{"signatures":{"go":"c.Policy().CreateTrafficSplitPolicy(ctx, \u0026policyv1.CreateTrafficSplitPolicyRequest{...})","python":"client.policy.createtrafficsplitpolicy(...)","typescript":"client.policy.createtrafficsplitpolicy({...})","cli":"tare api policy traffic-split-policies create --traffic-split-policy $TRAFFIC_SPLIT_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"traffic_split_policy\": {}\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy traffic-split-policies create --traffic-split-policy $TRAFFIC_SPLIT_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"traffic_split_policy\": {}\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/traffic-split-policies","slug":"create-a-traffic-split-policy"}
Get a traffic split policy
What it does: Returns a single traffic split policy by id.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to fetch. |
customer_id | no | Optional: customer (tenant) scope for future project-scoped filtering. |
project_id | no | Optional: project scope for future project-scoped filtering. |
Response fields:
| Field | Required | Description |
|---|---|---|
traffic_split_policy | no | The requested policy. |
{"signatures":{"go":"c.Policy().GetTrafficSplitPolicy(ctx, \u0026policyv1.GetTrafficSplitPolicyRequest{...})","python":"client.policy.gettrafficsplitpolicy(...)","typescript":"client.policy.gettrafficsplitpolicy({...})","cli":"tare api policy traffic-split-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/traffic-split-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy traffic-split-policies get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/traffic-split-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/traffic-split-policies/{id}","slug":"get-a-traffic-split-policy"}
List traffic split policies
What it does: Returns traffic split policies matching the specified filters.
Request fields:
| Field | Required | Description |
|---|---|---|
page | no | Cursor-pagination inputs. |
target_scope_types | no | Filter to policies with these target scope types. |
statuses | no | Filter to policies in these statuses. |
target_key_id | no | Filter to policies targeting this target_key_id. |
target_project_id | no | Filter to policies targeting this target_project_id. |
customer_id | no | Optional: customer (tenant) scope for future project-scoped filtering. |
project_id | no | Optional: project scope for future project-scoped filtering. |
Response fields:
| Field | Required | Description |
|---|---|---|
traffic_split_policies | no | Policies matching the request filters, one page's worth. |
page | no | Cursor-pagination outputs. |
total | no | Total count of matching policies across all pages. |
{"signatures":{"go":"c.Policy().ListTrafficSplitPolicies(ctx, \u0026policyv1.ListTrafficSplitPoliciesRequest{...})","python":"client.policy.listtrafficsplitpolicies(...)","typescript":"client.policy.listtrafficsplitpolicies({...})","cli":"tare api policy traffic-split-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/traffic-split-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy traffic-split-policies list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/traffic-split-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/traffic-split-policies","slug":"list-traffic-split-policies"}
Update a traffic split policy
What it does: Updates mutable traffic split policy fields. Omitted/empty scalar string fields leave the existing value untouched. The policy id must be set inside the traffic_split_policy field.
Request fields:
| Field | Required | Description |
|---|---|---|
traffic_split_policy | yes | Required: policy to update. traffic_split_policy.id must be set. Partial update semantics: omitted/empty scalar string fields leave the existing value untouched. Enum fields set to *_UNSPECIFIED leave the existing value untouched. |
customer_id | yes | Required: customer (tenant) that owns the target policy. |
project_id | yes | Required: project that owns the target policy. |
Response fields:
| Field | Required | Description |
|---|---|---|
traffic_split_policy | no | The updated policy with server-assigned fields populated. |
{"signatures":{"go":"c.Policy().UpdateTrafficSplitPolicy(ctx, \u0026policyv1.UpdateTrafficSplitPolicyRequest{...})","python":"client.policy.updatetrafficsplitpolicy(...)","typescript":"client.policy.updatetrafficsplitpolicy({...})","cli":"tare api policy traffic-split-policies update --traffic-split-policy $TRAFFIC_SPLIT_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"traffic_split_policy\": {}\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy traffic-split-policies update --traffic-split-policy $TRAFFIC_SPLIT_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"traffic_split_policy\": {}\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/traffic-split-policies/{traffic_split_policy.id}","slug":"update-a-traffic-split-policy"}
Delete a traffic split policy
What it does: Deletes a traffic split policy.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to delete. |
customer_id | yes | Required: customer (tenant) that owns the target policy. |
project_id | yes | Required: project that owns the target policy. |
{"signatures":{"go":"c.Policy().DeleteTrafficSplitPolicy(ctx, \u0026policyv1.DeleteTrafficSplitPolicyRequest{...})","python":"client.policy.deletetrafficsplitpolicy(...)","typescript":"client.policy.deletetrafficsplitpolicy({...})","cli":"tare api policy traffic-split-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy traffic-split-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/traffic-split-policies/{id}","slug":"delete-a-traffic-split-policy"}
Set traffic split policy status
What it does: Toggles a traffic split policy's active/inactive state (is_active).
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to update. |
status | yes | Required: new operational status for the policy. |
customer_id | yes | Required: customer (tenant) that owns the target policy. |
project_id | yes | Required: project that owns the target policy. |
Response fields:
| Field | Required | Description |
|---|---|---|
traffic_split_policy | no | The policy with the updated status. |
{"signatures":{"go":"c.Policy().SetTrafficSplitPolicyStatus(ctx, \u0026policyv1.SetTrafficSplitPolicyStatusRequest{...})","python":"client.policy.settrafficsplitpolicystatus(...)","typescript":"client.policy.settrafficsplitpolicystatus({...})","cli":"tare api policy traffic-split-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies/01H.../status\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"status\": \"...\"\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy traffic-split-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/traffic-split-policies/01H.../status\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"status\": \"...\"\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/traffic-split-policies/{id}/status","slug":"set-traffic-split-policy-status"}
List unified policies
Changed in v0.5.0 (new features): The unified policy list now includes attribute-routing policies alongside the budget, rate-limit, fallback-chain and traffic-split rows, naming each policy's target, effective project, and monitor or enforce mode, and appearing only where the caller could read it directly. For these rows match_count counts the eligible keys for which the policy is the enabled winner; a paused policy reports zero.
What it does: Returns a read-only, paginated list for the caller's tenant. Budget, rate-limit, fallback-chain and traffic-split policies include only PROJECT and TAG targets. Their KEY targets remain on the key's config page; the other legacy budget/rate-limit scopes remain excluded. Attribute-routing policies include PROJECT and KEY targets. A row appears only when the caller could read it through GetAttributeRoutingPolicy in its effective project. Visibility and request filters apply before totals and pagination. Mutations still use each family's type-specific RPCs. UnifiedPolicy.match_count retains target membership counts for the existing families. Attribute-routing coverage counts eligible keys where the policy is the enabled winner, independent of monitor/enforce mode.
Request fields:
| Field | Required | Description |
|---|---|---|
page | no | Cursor-pagination inputs. |
customer_id | no | Optional: customer (tenant) scope. Resolved the same way every other PolicyService read RPC resolves it (resolvePolicyCustomerID): defaults from the caller's authenticated claims when unset. |
types | no | Filter to these policy types. Empty means all supported types. |
statuses | no | Filter to policies in these statuses. Empty means all statuses. |
Response fields:
| Field | Required | Description |
|---|---|---|
policies | no | Policies matching the request filters, one page's worth. Sorted by updated_at descending (most recently changed first). |
page | no | Cursor-pagination outputs. |
total | no | Total count of matching policies across all pages. |
{"signatures":{"go":"c.Policy().ListPolicies(ctx, \u0026policyv1.ListPoliciesRequest{...})","python":"client.policy.listpolicies(...)","typescript":"client.policy.listpolicies({...})","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/policies","slug":"list-unified-policies"}
Create a request attribute
Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.
What it does: Adds one entry to the customer's org-wide routing vocabulary.
Request fields:
| Field | Required | Description |
|---|---|---|
request_attribute | yes | Required: vocabulary entry to create. id must be absent (server-assigned). |
customer_id | yes | Required: customer (tenant) that will own the entry. The vocabulary is org-wide, so this is the entry's real owning scope. |
project_id | yes | Required: project the caller is acting in. Read by the auth layer to authorize the caller; it does NOT scope the created entry, which is org-wide. See the file-level PROJECT SCOPING note. |
Response fields:
| Field | Required | Description |
|---|---|---|
request_attribute | no | The created entry with server-assigned fields populated. |
{"signatures":{"go":"c.Policy().CreateRequestAttribute(ctx, \u0026policyv1.CreateRequestAttributeRequest{...})","python":"client.policy.createrequestattribute(...)","typescript":"client.policy.createrequestattribute({...})","cli":"tare api policy request-attributes create --request-attribute $REQUEST_ATTRIBUTE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/request-attributes\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"request_attribute\": {}\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy request-attributes create --request-attribute $REQUEST_ATTRIBUTE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/request-attributes\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"request_attribute\": {}\n }'"},"persona":"Admin","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/request-attributes","slug":"create-a-request-attribute"}
Get a request attribute
Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.
What it does: Returns a single vocabulary entry by id, including the policies that reference it so a caller can tell whether deleting it would break a live rule.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the entry to fetch. |
customer_id | no | Optional: customer (tenant) scope. |
project_id | no | Optional: project scope. |
Response fields:
| Field | Required | Description |
|---|---|---|
request_attribute | no | The requested entry, with referencing_policy_count and the full referencing_policies list populated. |
{"signatures":{"go":"c.Policy().GetRequestAttribute(ctx, \u0026policyv1.GetRequestAttributeRequest{...})","python":"client.policy.getrequestattribute(...)","typescript":"client.policy.getrequestattribute({...})","cli":"tare api policy request-attributes get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/request-attributes/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy request-attributes get \u003cid\u003e","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/request-attributes/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/request-attributes/{id}","slug":"get-a-request-attribute"}
List request attributes
Changed in v0.5.0 (behaviour changes): ListRequestAttributes now accepts an optional search, returns unfiltered catalog stats, supports sorting by name, value_type or referencing_policy_count, and rejects unsupported page.filter or page.order_by values with InvalidArgument instead of ignoring them.
Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.
What it does: Returns the customer's routing vocabulary, ordered by name.
Request fields:
| Field | Required | Description |
|---|---|---|
page | no | Cursor-pagination inputs. page.order_by accepts a single field, one of name, value_type or referencing_policy_count, optionally followed by asc or desc (AIP-132). Empty order_by means name asc. page.filter is not supported and is rejected rather than ignored. Page tokens are bound to the normalized order, search and customer scope. |
customer_id | no | Optional: customer (tenant) scope. |
project_id | no | Optional: project scope. |
search | no | Optional case-insensitive substring search on the attribute name or any allowed value. Surrounding whitespace is ignored. Applies before sorting and pagination, and response.total counts the matching entries. |
Response fields:
| Field | Required | Description |
|---|---|---|
request_attributes | no | The matching vocabulary, one page's worth in the requested order. |
page | no | Cursor-pagination outputs. |
total | no | Total count of matching entries across all pages. |
stats | no | Unfiltered catalog totals for the overview cards. These counts ignore search and pagination and are computed over the same customer scope. |
{"signatures":{"go":"c.Policy().ListRequestAttributes(ctx, \u0026policyv1.ListRequestAttributesRequest{...})","python":"client.policy.listrequestattributes(...)","typescript":"client.policy.listrequestattributes({...})","cli":"tare api policy request-attributes list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/request-attributes\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy request-attributes list","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/request-attributes\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/request-attributes","slug":"list-request-attributes"}
Update a request attribute
Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.
What it does: Replaces a vocabulary entry's name, value type and allowed values. Removing an allowed value that a live rule compares against is permitted and does NOT break the rule structurally; it makes that condition stop matching, which is why fraser#8662 warns first.
Request fields:
| Field | Required | Description |
|---|---|---|
request_attribute | yes | Required: entry to update. request_attribute.id must be set. name, value_type and allowed_values are replaced wholesale. |
customer_id | yes | Required: customer (tenant) that owns the entry. |
project_id | yes | Required: project the caller is acting in. Authorization only. |
Response fields:
| Field | Required | Description |
|---|---|---|
request_attribute | no | The updated entry. |
{"signatures":{"go":"c.Policy().UpdateRequestAttribute(ctx, \u0026policyv1.UpdateRequestAttributeRequest{...})","python":"client.policy.updaterequestattribute(...)","typescript":"client.policy.updaterequestattribute({...})","cli":"tare api policy request-attributes update --request-attribute $REQUEST_ATTRIBUTE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/request-attributes/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"request_attribute\": {}\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy request-attributes update --request-attribute $REQUEST_ATTRIBUTE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/request-attributes/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"request_attribute\": {}\n }'"},"persona":"Admin","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/request-attributes/{request_attribute.id}","slug":"update-a-request-attribute"}
Delete a request attribute
Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.
What it does: Removes a vocabulary entry. Refused with FailedPrecondition, naming the blocking policies, when a live rule condition still compares against it.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the entry to delete. |
customer_id | yes | Required: customer (tenant) that owns the entry. |
project_id | yes | Required: project the caller is acting in. Authorization only. |
{"signatures":{"go":"c.Policy().DeleteRequestAttribute(ctx, \u0026policyv1.DeleteRequestAttributeRequest{...})","python":"client.policy.deleterequestattribute(...)","typescript":"client.policy.deleterequestattribute({...})","cli":"tare api policy request-attributes delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/request-attributes/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy request-attributes delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/request-attributes/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Admin","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/request-attributes/{id}","slug":"delete-a-request-attribute"}
Create an attribute routing policy
Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.
What it does: Creates an ordered rule list bound to a project or a key. The created policy is always in MONITOR mode: nothing moves traffic until SetAttributeRoutingPolicyMode flips it. KNOWN LIMITATION. A destination is checked against the target project's catalog at save time, which is early feedback rather than a guarantee. Availability for a given key also depends on the provider, the project's provider filter, the key's own route map and the gateway binding, all of which are resolved when the routing snapshot is rendered. A rule can therefore save cleanly and still never fire, because the destination was dropped at render time.
Request fields:
| Field | Required | Description |
|---|---|---|
attribute_routing_policy | yes | Required: policy to create. id must be absent (server-assigned), and mode is ignored -- a created policy is always in MONITOR. |
customer_id | yes | Required: customer (tenant) that will own the policy. |
project_id | yes | Required: project that will own the policy. |
Response fields:
| Field | Required | Description |
|---|---|---|
attribute_routing_policy | no | The created policy, in MONITOR mode, with server-assigned rule ids. |
{"signatures":{"go":"c.Policy().CreateAttributeRoutingPolicy(ctx, \u0026policyv1.CreateAttributeRoutingPolicyRequest{...})","python":"client.policy.createattributeroutingpolicy(...)","typescript":"client.policy.createattributeroutingpolicy({...})","cli":"tare api policy attribute-routing-policies create --attribute-routing-policy $ATTRIBUTE_ROUTING_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"attribute_routing_policy\": {}\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy attribute-routing-policies create --attribute-routing-policy $ATTRIBUTE_ROUTING_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"attribute_routing_policy\": {}\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/attribute-routing-policies","slug":"create-an-attribute-routing-policy"}
Get an attribute routing policy
Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.
What it does: Returns a single policy with its ordered rules and their conditions.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to fetch. |
customer_id | no | Optional: customer (tenant) scope. |
project_id | yes | Required: project against which the policy is authorized. |
Response fields:
| Field | Required | Description |
|---|---|---|
attribute_routing_policy | no | The requested policy with its ordered rules and conditions. |
{"signatures":{"go":"c.Policy().GetAttributeRoutingPolicy(ctx, \u0026policyv1.GetAttributeRoutingPolicyRequest{...})","python":"client.policy.getattributeroutingpolicy(...)","typescript":"client.policy.getattributeroutingpolicy({...})","cli":"tare api policy attribute-routing-policies get \u003cid\u003e --project-id $PROJECT_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/attribute-routing-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy attribute-routing-policies get \u003cid\u003e --project-id $PROJECT_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/attribute-routing-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/attribute-routing-policies/{id}","slug":"get-an-attribute-routing-policy"}
List attribute routing policies
Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.
What it does: Returns policies matching the filters, WITHOUT their rule bodies: the list surfaces show targets and modes. Use GetAttributeRoutingPolicy to load rules.
Request fields:
| Field | Required | Description |
|---|---|---|
page | no | Cursor-pagination inputs. |
scope_types | no | Filter to policies with these scope types. |
statuses | no | Filter to policies in these statuses. |
target_project_id | no | Filter to policies targeting this target_project_id (project slug). |
customer_id | no | Optional: customer (tenant) scope. |
project_id | yes | Required: project boundary for the list. Results are always restricted to policies effective for this project. |
Response fields:
| Field | Required | Description |
|---|---|---|
attribute_routing_policies | no | Policies matching the filters, WITHOUT their rule bodies. |
page | no | Cursor-pagination outputs. |
total | no | Total count of matching policies across all pages. |
{"signatures":{"go":"c.Policy().ListAttributeRoutingPolicies(ctx, \u0026policyv1.ListAttributeRoutingPoliciesRequest{...})","python":"client.policy.listattributeroutingpolicies(...)","typescript":"client.policy.listattributeroutingpolicies({...})","cli":"tare api policy attribute-routing-policies list --project-id $PROJECT_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/attribute-routing-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy attribute-routing-policies list --project-id $PROJECT_ID","curl":"curl \"${AGENTROUTER_BASE_URL}/v1/policy/attribute-routing-policies\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"GET","httpPath":"/v1/policy/attribute-routing-policies","slug":"list-attribute-routing-policies"}
Update an attribute routing policy
Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.
What it does: Applies a partial update. A present rules field replaces the ENTIRE rule list: a rule carrying its id is updated in place, a rule with no id is created, and a rule left out is deleted. Omitting rules leaves the list untouched. Mode, status, scope_type, target_api_key_id, and target_project_id are NOT settable here. KNOWN LIMITATION. A destination is checked against the target project's catalog at save time, which is early feedback rather than a guarantee. Availability for a given key also depends on the provider, the project's provider filter, the key's own route map and the gateway binding, all of which are resolved when the routing snapshot is rendered. A rule can therefore save cleanly and still never fire, because the destination was dropped at render time.
Request fields:
| Field | Required | Description |
|---|---|---|
attribute_routing_policy | yes | Required: policy to update. attribute_routing_policy.id must be set. Partial update: an omitted/empty scalar leaves the stored value untouched. Mode and status are NOT settable here; use SetAttributeRoutingPolicyMode and SetAttributeRoutingPolicyStatus. scope_type, target_api_key_id, and target_project_id are immutable; create a new policy to change its target. |
customer_id | yes | Required: customer (tenant) that owns the policy. |
project_id | yes | Required: project that owns the policy. |
clear_rules | no | Delete every rule, leaving a policy that always takes its default. proto3 cannot tell an omitted repeated field from an empty one, and both are meaningful here, so emptying the list needs its own signal. A non-empty attribute_routing_policy.rules replaces the whole list regardless of this flag; an empty rules with clear_rules = false (the default) leaves the stored rules untouched. Mirrors clear_tags / clear_scopes on UpdateApiKeyRequest. |
Response fields:
| Field | Required | Description |
|---|---|---|
attribute_routing_policy | no | The updated policy with its resulting rule list. |
{"signatures":{"go":"c.Policy().UpdateAttributeRoutingPolicy(ctx, \u0026policyv1.UpdateAttributeRoutingPolicyRequest{...})","python":"client.policy.updateattributeroutingpolicy(...)","typescript":"client.policy.updateattributeroutingpolicy({...})","cli":"tare api policy attribute-routing-policies update --attribute-routing-policy $ATTRIBUTE_ROUTING_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"attribute_routing_policy\": {},\n \"clear_rules\": false\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy attribute-routing-policies update --attribute-routing-policy $ATTRIBUTE_ROUTING_POLICY --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X PATCH \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"attribute_routing_policy\": {},\n \"clear_rules\": false\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"PATCH","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/attribute-routing-policies/{attribute_routing_policy.id}","slug":"update-an-attribute-routing-policy"}
Delete an attribute routing policy
Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.
What it does: Removes a policy; its rules and conditions go with it.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to delete. |
customer_id | yes | Required: customer (tenant) that owns the policy. |
project_id | yes | Required: project that owns the policy. |
{"signatures":{"go":"c.Policy().DeleteAttributeRoutingPolicy(ctx, \u0026policyv1.DeleteAttributeRoutingPolicyRequest{...})","python":"client.policy.deleteattributeroutingpolicy(...)","typescript":"client.policy.deleteattributeroutingpolicy({...})","cli":"tare api policy attribute-routing-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy attribute-routing-policies delete \u003cid\u003e --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X DELETE \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H...\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\""},"persona":"Authenticated (API key or session token)","httpVerb":"DELETE","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/attribute-routing-policies/{id}","slug":"delete-an-attribute-routing-policy"}
Set attribute routing policy status
Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.
What it does: Switches a policy on or off. Independent of mode: pausing a policy does not forget whether it monitors or enforces.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to update. |
status | yes | Required: new operational status. |
customer_id | yes | Required: customer (tenant) that owns the policy. |
project_id | yes | Required: project that owns the policy. |
Response fields:
| Field | Required | Description |
|---|---|---|
attribute_routing_policy | no | The policy with the updated status. |
{"signatures":{"go":"c.Policy().SetAttributeRoutingPolicyStatus(ctx, \u0026policyv1.SetAttributeRoutingPolicyStatusRequest{...})","python":"client.policy.setattributeroutingpolicystatus(...)","typescript":"client.policy.setattributeroutingpolicystatus({...})","cli":"tare api policy attribute-routing-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H.../status\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"status\": \"...\"\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy attribute-routing-policies set-status --id $ID --status $STATUS --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H.../status\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"status\": \"...\"\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/attribute-routing-policies/{id}/status","slug":"set-attribute-routing-policy-status"}
Set attribute routing policy mode
Changed in v0.4.0 (new features): Request attribute catalogs and attribute-based routing policies can now be managed through the API, with separate controls for activation and monitor or enforce mode.
What it does: Flips a policy between monitoring and enforcing. Its own RPC, and its own audit action, because this is the moment live traffic starts moving.
Request fields:
| Field | Required | Description |
|---|---|---|
id | yes | Required: uuid of the policy to update. |
mode | yes | Required: new mode. Flipping to ENFORCE is the moment live traffic starts moving, which is why it is this RPC rather than part of Update. |
customer_id | yes | Required: customer (tenant) that owns the policy. |
project_id | yes | Required: project that owns the policy. |
Response fields:
| Field | Required | Description |
|---|---|---|
attribute_routing_policy | no | The policy with the updated mode. |
{"signatures":{"go":"c.Policy().SetAttributeRoutingPolicyMode(ctx, \u0026policyv1.SetAttributeRoutingPolicyModeRequest{...})","python":"client.policy.setattributeroutingpolicymode(...)","typescript":"client.policy.setattributeroutingpolicymode({...})","cli":"tare api policy attribute-routing-policies set-mode --id $ID --mode $MODE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H.../mode\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"mode\": \"...\"\n }'"},"examples":{"go":"// No Go SDK wrapper for PolicyService yet -- use the CLI or curl example below.","python":"# No Python SDK wrapper for PolicyService yet -- use the CLI or curl example below.","typescript":"// No TypeScript SDK wrapper for PolicyService yet -- use the CLI or curl example below.","cli":"tare api policy attribute-routing-policies set-mode --id $ID --mode $MODE --customer-id $CUSTOMER_ID --project-id $PROJECT_ID","curl":"curl -X POST \"${AGENTROUTER_BASE_URL}/v1/customers/cust_01H.../projects/proj_01H.../policy/attribute-routing-policies/01H.../mode\" \\\n -H \"Authorization: Bearer ak-${AGENTROUTER_API_KEY}\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"mode\": \"...\"\n }'"},"persona":"Authenticated (API key or session token)","httpVerb":"POST","httpPath":"/v1/customers/{customer_id}/projects/{project_id}/policy/attribute-routing-policies/{id}/mode","slug":"set-attribute-routing-policy-mode"}