---
title: "Create a hook rule"
method: POST
path: "/api/hook-rules"
tags: ["HookRules"]
---

# Create a hook rule

`POST /api/hook-rules`

## Request

- Base URL: `http://localhost:38200`
- URL: `http://localhost:38200/api/hook-rules`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `token`

A patch naming a forbidden field (lifecycle, scope, tenantId, origin and the rest of the T916 forbidden list) or a reserved `__` metadata key is refused here, at save time. Patterns use a linear-time subset (no anchors, backreferences or lookaround).

## Request body

- HookRuleInput
  - `name` string, required
  - `enabled` boolean
  - `priority` integer
  - `match` HookRuleMatch
    - `ops` string[]: Absent means [create, update]. delete, review and retrieve.before are opt-in and cannot share a rule with create or update.
    - `types` string[]
    - `workspaces` string[]
    - `tagsAny` string[]
    - `tagsAll` string[]
    - `text` HookRulePattern
      - `source` string, required: Linear-time subset: literals, ., [classes], \d \w \s, * + ? {m,n} (n <= 100), | and (groups). No anchors, backreferences or lookaround.
      - `caseInsensitive` boolean
  - `actions` HookRuleAction[], required
    - `type` 'addTags' | 'setProperties' | 'patch' | 'redact' | 'quarantine' | 'deny' | 'narrow', required

## Response `201`

Created rule.

- HookRule
  - `name` string, required
  - `enabled` boolean
  - `priority` integer
  - `match` HookRuleMatch
    - `ops` string[]: Absent means [create, update]. delete, review and retrieve.before are opt-in and cannot share a rule with create or update.
    - `types` string[]
    - `workspaces` string[]
    - `tagsAny` string[]
    - `tagsAll` string[]
    - `text` HookRulePattern
      - `source` string, required: Linear-time subset: literals, ., [classes], \d \w \s, * + ? {m,n} (n <= 100), | and (groups). No anchors, backreferences or lookaround.
      - `caseInsensitive` boolean
  - `actions` HookRuleAction[], required
    - `type` 'addTags' | 'setProperties' | 'patch' | 'redact' | 'quarantine' | 'deny' | 'narrow', required
  - `id` integer
  - `createdAt` string, date-time
  - `updatedAt` string, date-time

## Other responses

- `400`: Request body/query failed Zod validation.
- `401`: Missing or invalid credentials.
- `403`: Admin or owner role (or an API key with admin scope) required.
- `409`: The tenant already holds the maximum number of rules.

---

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