Skip to main content
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.

Extracted rules vs manual rules

ExtractedManual
Created byAutomatic, on Style Guide create or updatePOST /api/v1/rules
Linked to Style GuideYes (styleGuide field populated)No
Scope on creationInherits Style Guide’s Content Group and languageSet explicitly in the request
Unlinked whenRule 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.
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:
{ "jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }

2. Poll the create job

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.
{
  "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.
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:
{
  "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.
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.
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:
{
  "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:
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.
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.

Creating a manual rule

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:
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:
FilterDescription
contentGroupIdsReturn rules scoped to any of these Content Group IDs
languagesReturn rules scoped to any of these locale codes
styleGuideIdsReturn only rules extracted from these Style Guides
activetrue / false — filter by active status
aiCheckEnabledtrue / false — filter by AI check flag
ruleTextCase-insensitive substring match against rule text
lastModifiedByFilter by user account IDs
Example — find all active rules for the marketing Content Group in English:
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.
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.
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.