> ## Documentation Index
> Fetch the complete documentation index at: https://developers.phrase.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Working with Rules

Rules are the writing instructions that Phrase uses to improve the translation quality for AI Translation
Agent and MT Optimize. Rules are also used for AI-powered quality checks. This guide walks through the full
lifecycle: from uploading a Style Guide and inspecting the extracted rules, to creating manual rules and updating
them over time.

For a conceptual overview of how Rules relate to Style Guides and Content Groups, see [Core Concepts](/en/api/style-guides/concepts).

## Extracted rules vs manual rules

|                           | Extracted                                                                                                 | Manual                        |
| ------------------------- | --------------------------------------------------------------------------------------------------------- | ----------------------------- |
| **Created by**            | Automatic, on Style Guide create or update                                                                | `POST /api/v1/rules`          |
| **Linked to Style Guide** | Yes (`styleGuide` field populated)                                                                        | No                            |
| **Scope on creation**     | Inherits Style Guide's Content Group and language                                                         | Set explicitly in the request |
| **Unlinked when**         | Rule text is edited, or content group/language scope is changed in any way (requires `forceUnlink: true`) | Never linked to begin with    |

Use extracted rules when your team maintains a Style Guide Markdown file as the source of truth. Use manual rules
for guidelines that live outside any Style Guide, or when you want to add or override individual rules without
uploading a new file.

## End-to-end walkthrough

### 1. Create a Style Guide

Upload a Markdown file using the v2 endpoint with a Content Group ID. The API returns a `jobId` immediately and
processes the file asynchronously.

```bash theme={null}
curl -X POST "https://eu.phrase.com/styleguide/api/v2/styleguides" \
  -H "Authorization: Bearer $JWT" \
  -F language=en-GB \
  -F name="English Style Guide" \
  -F contentGroupId="6a428641ba54ab39ae56da64" \
  -F file=@./style-guide.md
```

Response:

```json theme={null}
{ "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }
```

### 2. Poll the create job

```bash theme={null}
curl "https://eu.phrase.com/styleguide/api/v1/styleguides/async/create-jobs/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
  -H "Authorization: Bearer $JWT"
```

Keep polling until `status` is `COMPLETED`. The `result` field contains the created Style Guide.

```json theme={null}
{
  "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "status": "COMPLETED",
  "result": {
    "id": "018e1234-5678-7890-abcd-ef1234567890",
    "name": "English Style Guide",
    "language": { "bcpCode": "en-GB", "description": "English (United Kingdom)", "language": "en" },
    "contentGroup": { "id": "6a428641ba54ab39ae56da64" }
  }
}
```

### 3. List extracted rules

After the job completes, list the rules that were extracted from the Style Guide. Filter by `styleGuideIds` to
retrieve only rules from this guide.

```bash theme={null}
curl -X POST "https://eu.phrase.com/styleguide/api/v1/rules/search" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "styleGuideIds": ["018e1234-5678-7890-abcd-ef1234567890"],
    "pageNumber": 0,
    "pageSize": 20
  }'
```

Each rule in the response includes its extracted text, scope, and a `styleGuide` reference pointing back to the source:

```json theme={null}
{
  "content": [
    {
      "id": "01900000-0000-7000-8000-000000000001",
      "rule": "Avoid passive voice in all user-facing content.",
      "active": true,
      "aiCheckEnabled": true,
      "allContentGroups": false,
      "allLanguages": false,
      "contentGroups": [{ "id": "6a428641ba54ab39ae56da64" }],
      "languages": [{ "bcpCode": "en-GB", "description": "English (United Kingdom)", "language": "en" }],
      "styleGuide": { "id": "018e1234-5678-7890-abcd-ef1234567890" }
    }
  ],
  "totalElements": 12,
  "totalPages": 1,
  "pageNumber": 0,
  "pageSize": 20,
  "numberOfElements": 12
}
```

### 4. Edit a rule

Use `PATCH /api/v1/rules/{id}` to update a rule. Only fields present (non-null) in the request body are applied —
omit a field to leave it unchanged.

<Warning>
  Editing a rule's text or scope **unlinks it from its source Style Guide**. The `styleGuide` field becomes `null`
  and the rule becomes standalone. This does not affect the Style Guide itself or its other extracted rules.

  Because this is permanent, the API will not perform an unlinking update unless the request explicitly sets
  `forceUnlink: true`. Without it, the request fails with `409 Conflict`
  (`RULE_UNLINK_REQUIRES_CONFIRMATION`) and none of the requested changes are applied.
</Warning>

```bash theme={null}
curl -X PATCH "https://eu.phrase.com/styleguide/api/v1/rules/01900000-0000-7000-8000-000000000001" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "rule": "Use active voice in all user-facing content."
  }'
```

Since this rule is linked to a Style Guide, the request above fails:

```json theme={null}
{
  "code": "RULE_UNLINK_REQUIRES_CONFIRMATION",
  "message": "This update would unlink the rule from its Style Guide. Set forceUnlink=true to confirm.",
  "detail": "Updating rule 01900000-0000-7000-8000-000000000001 would unlink it from its Style Guide"
}
```

Retry with `forceUnlink: true` to confirm the unlink and apply the change:

```bash theme={null}
curl -X PATCH "https://eu.phrase.com/styleguide/api/v1/rules/01900000-0000-7000-8000-000000000001" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "rule": "Use active voice in all user-facing content.",
    "forceUnlink": true
  }'
```

Updates that do not change the rule text, content group scope, or language scope at all (for example, only
toggling `active` or `aiCheckEnabled`, or resubmitting the same scope the rule already has) never unlink the rule,
so `forceUnlink` is not required for them.

<Tip>
  Rule changes take effect immediately for any running jobs in the affected Content Group. Make rule edits when no
  jobs for that Content Group are active, and verify your rules before starting new jobs.
</Tip>

## Creating a manual rule

```bash theme={null}
curl -X POST "https://eu.phrase.com/styleguide/api/v1/rules" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "rule": "Use the Oxford comma in all list items.",
    "allContentGroups": false,
    "contentGroupIds": ["6a428641ba54ab39ae56da64", "6a2eb0d1ed7a69bbb1b53d06"],
    "allLanguages": false,
    "languages": ["en-GB", "en-US"],
    "active": true,
    "aiCheckEnabled": true
  }'
```

To create a rule that applies everywhere, set both `allContentGroups` and `allLanguages` to `true` and omit
`contentGroupIds` and `languages`:

```bash theme={null}
curl -X POST "https://eu.phrase.com/styleguide/api/v1/rules" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "rule": "Do not use exclamation marks in formal content.",
    "allContentGroups": true,
    "allLanguages": true
  }'
```

## Filtering rules

The `POST /api/v1/rules/search` endpoint supports several filters that can be combined:

| Filter            | Description                                           |
| ----------------- | ----------------------------------------------------- |
| `contentGroupIds` | Return rules scoped to any of these Content Group IDs |
| `languages`       | Return rules scoped to any of these locale codes      |
| `styleGuideIds`   | Return only rules extracted from these Style Guides   |
| `active`          | `true` / `false` — filter by active status            |
| `aiCheckEnabled`  | `true` / `false` — filter by AI check flag            |
| `ruleText`        | Case-insensitive substring match against rule text    |
| `lastModifiedBy`  | Filter by user account IDs                            |

Example — find all active rules for the `marketing` Content Group in English:

```bash theme={null}
curl -X POST "https://eu.phrase.com/styleguide/api/v1/rules/search" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "contentGroupIds": ["6a428641ba54ab39ae56da64"],
    "languages": ["en-GB"],
    "active": true,
    "pageNumber": 0,
    "pageSize": 50
  }'
```

## Disabling a rule for AI checks

Set `aiCheckEnabled: false` to keep a rule in the Style Guide record without using it for AI-powered Quality checks.
This is useful for rules that are aspirational or under review.

```bash theme={null}
curl -X PATCH "https://eu.phrase.com/styleguide/api/v1/rules/01900000-0000-7000-8000-000000000001" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{ "aiCheckEnabled": false }'
```

To re-enable, patch with `"aiCheckEnabled": true`.

## Deleting a rule

`DELETE /api/v1/rules/{id}` permanently removes a rule. This does not affect the source Style Guide or any other
extracted rules.

```bash theme={null}
curl -X DELETE "https://eu.phrase.com/styleguide/api/v1/rules/01900000-0000-7000-8000-000000000001" \
  -H "Authorization: Bearer $JWT"
```

A successful deletion returns `204 No Content`.
