---
title: "Create a policy rule"
method: POST
path: "/api/v1/policies"
tags: ["Policies"]
---

# Create a policy rule

`POST /api/v1/policies`

## Request

- Base URL: `https://dashboard.sealgate.ai`
- URL: `https://dashboard.sealgate.ai/api/v1/policies`
- Auth: HTTP bearer

Create a CEL-based policy rule. Requires the admin role.

## Request body

- CreatePolicyRequest
  - `name` string, required: Rule name
  - `rule_id` string, required: Unique rule identifier
  - `description` string, nullable
  - `cel_expression` string, nullable: CEL filter expression
  - `phase` string: Evaluation phase: pre or post. A post-phase rule cannot carry a require_approval action
  - `status` string: Rule status: enabled, disabled, or tentative
  - `priority` integer
  - `principal_scope` PrincipalScope
    - `is_global` boolean: Whether the rule applies to all users
    - `include_roles` string[]
    - `include_users` string[]
    - `exclude_roles` string[]
    - `exclude_users` string[]
  - `resource_scope` ResourceScope
    - `element_types` string[]: Element types: tool, resource, prompt
    - `servers` string[]: MCP server names
    - `name_patterns` string[]: Regex patterns for element names
  - `actions` PolicyAction[]
    - `action_type` string, required: Action type: block, require_approval, allow_override, mark_private, mark_untrusted, mark_write, set_acl, add_tag
    - `acl_level` string, nullable: ACL level for set_acl action
    - `tag_key` string, nullable
    - `tag_value` string, nullable
    - `block_reason` string, nullable
    - `approval_reason` string, nullable: Plain-language reason shown to the human deciding
    - `approval_channels` string[]: Channels to pin the approval prompt to
    - `approval_timeout_s` number, nullable: How long to hold the call awaiting a decision; null uses the server default
    - `approval_on_timeout` 'deny' | 'allow' | 'null', nullable: What happens when nobody answers in time; null means deny (fail closed). 'allow' is deprecated and reported as 'deny'

## Response `201`

The created policy rule

- PolicyRule: A CEL-based policy rule.
  - `id` integer, required: Database row ID
  - `rule_id` string, required: Unique rule identifier
  - `name` string, required: Human-readable rule name
  - `description` string, nullable
  - `cel_expression` string, nullable: CEL filter expression
  - `phase` string, required: Evaluation phase: pre or post
  - `status` string, required: Rule status: enabled, disabled, or tentative
  - `priority` integer, required: Rule priority (higher evaluated first)
  - `domain` string, nullable: Domain scope (null = global)
  - `principal_scope` PrincipalScope, required
    - `is_global` boolean: Whether the rule applies to all users
    - `include_roles` string[]
    - `include_users` string[]
    - `exclude_roles` string[]
    - `exclude_users` string[]
  - `resource_scope` ResourceScope, required
    - `element_types` string[]: Element types: tool, resource, prompt
    - `servers` string[]: MCP server names
    - `name_patterns` string[]: Regex patterns for element names
  - `actions` PolicyAction[], required
    - `action_type` string, required: Action type: block, require_approval, allow_override, mark_private, mark_untrusted, mark_write, set_acl, add_tag
    - `acl_level` string, nullable: ACL level for set_acl action
    - `tag_key` string, nullable
    - `tag_value` string, nullable
    - `block_reason` string, nullable
    - `approval_reason` string, nullable: Plain-language reason shown to the human deciding
    - `approval_channels` string[]: Channels to pin the approval prompt to
    - `approval_timeout_s` number, nullable: How long to hold the call awaiting a decision; null uses the server default
    - `approval_on_timeout` 'deny' | 'allow' | 'null', nullable: What happens when nobody answers in time; null means deny (fail closed). 'allow' is deprecated and reported as 'deny'
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required

## Other responses

- `400`: The request was invalid
- `401`: Missing or invalid API key
- `403`: The caller's role is not permitted to perform this action
- `409`: The resource already exists or conflicts with current state
- `422`: Request validation failed

---

[API](https://skmtc.dev/sealgate/apis/sealgate-management-api.md) · [All operations](https://skmtc.dev/sealgate/apis/sealgate-management-api/llms.txt) · [OpenAPI document](https://skmtc.dev/sealgate/apis/sealgate-management-api/revisions/c9ca2e599065?raw)
