curl --request PATCH \
--url https://eu.phrase.com/styleguide/api/v1/rules/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"rule": "Avoid passive voice in all user-facing content.",
"allContentGroups": true,
"contentGroupIds": [
"<string>"
],
"allLanguages": true,
"languages": [
"<string>"
],
"active": true,
"aiCheckEnabled": true,
"forceUnlink": false
}
'import requests
url = "https://eu.phrase.com/styleguide/api/v1/rules/{id}"
payload = {
"rule": "Avoid passive voice in all user-facing content.",
"allContentGroups": True,
"contentGroupIds": ["<string>"],
"allLanguages": True,
"languages": ["<string>"],
"active": True,
"aiCheckEnabled": True,
"forceUnlink": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
rule: 'Avoid passive voice in all user-facing content.',
allContentGroups: true,
contentGroupIds: ['<string>'],
allLanguages: true,
languages: ['<string>'],
active: true,
aiCheckEnabled: true,
forceUnlink: false
})
};
fetch('https://eu.phrase.com/styleguide/api/v1/rules/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://eu.phrase.com/styleguide/api/v1/rules/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'rule' => 'Avoid passive voice in all user-facing content.',
'allContentGroups' => true,
'contentGroupIds' => [
'<string>'
],
'allLanguages' => true,
'languages' => [
'<string>'
],
'active' => true,
'aiCheckEnabled' => true,
'forceUnlink' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://eu.phrase.com/styleguide/api/v1/rules/{id}"
payload := strings.NewReader("{\n \"rule\": \"Avoid passive voice in all user-facing content.\",\n \"allContentGroups\": true,\n \"contentGroupIds\": [\n \"<string>\"\n ],\n \"allLanguages\": true,\n \"languages\": [\n \"<string>\"\n ],\n \"active\": true,\n \"aiCheckEnabled\": true,\n \"forceUnlink\": false\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://eu.phrase.com/styleguide/api/v1/rules/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"rule\": \"Avoid passive voice in all user-facing content.\",\n \"allContentGroups\": true,\n \"contentGroupIds\": [\n \"<string>\"\n ],\n \"allLanguages\": true,\n \"languages\": [\n \"<string>\"\n ],\n \"active\": true,\n \"aiCheckEnabled\": true,\n \"forceUnlink\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://eu.phrase.com/styleguide/api/v1/rules/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"rule\": \"Avoid passive voice in all user-facing content.\",\n \"allContentGroups\": true,\n \"contentGroupIds\": [\n \"<string>\"\n ],\n \"allLanguages\": true,\n \"languages\": [\n \"<string>\"\n ],\n \"active\": true,\n \"aiCheckEnabled\": true,\n \"forceUnlink\": false\n}"
response = http.request(request)
puts response.read_body{
"id": "01900000-0000-7000-8000-000000000001",
"rule": "Avoid passive voice in all user-facing content.",
"active": true,
"aiCheckEnabled": true,
"allContentGroups": true,
"allLanguages": true,
"contentGroups": [
{
"id": "cg-marketing-en"
}
],
"languages": [
{
"bcpCode": "en-GB",
"description": "English (United Kingdom)",
"language": "cs",
"region": "gb",
"script": "LATN"
}
],
"createdAt": "2024-01-15T10:30:00Z",
"lastModifiedAt": "2024-06-01T14:22:00Z",
"name": "No passive voice",
"omittedReason": "<string>",
"eligibilityCheckedAt": "2024-06-01T14:22:05Z",
"styleGuide": null,
"createdBy": null,
"lastModifiedBy": null
}{
"code": "<string>",
"message": "<string>",
"detail": "<string>"
}{
"code": "<string>",
"message": "<string>",
"detail": "<string>"
}{
"code": "<string>",
"message": "<string>",
"detail": "<string>"
}{
"code": "<string>",
"message": "<string>",
"detail": "<string>"
}{
"code": "<string>",
"message": "<string>",
"detail": "<string>"
}Update a Rule
Updates a Rule. Only fields present (non-null) in the request body are applied.
Unlinking from a Style Guide
Editing the rule text, or removing the linked Style Guide’s content group or language, would unlink the rule from its Style Guide:
| Change would unlink? | forceUnlink | Result |
|---|---|---|
| Yes | true | Applied; rule is unlinked from its Style Guide |
| Yes | false / omitted | 409 RULE_UNLINK_REQUIRES_CONFIRMATION; no changes applied |
| No | any | Applied normally |
Active-rule and AI-check limits
The active-rule / active-AI-check limits for the rule’s (Content Group, Language) scope are
re-checked only when the resulting state could newly breach them — an unchanged rule (same
scope, same active/AI-check state) is never re-checked, since it already satisfied the
limits under its prior scope. What happens on a breach depends on whether the caller
explicitly requested active=true/aiCheckEnabled=true, or the breach is caused solely by
a content-group/language scope change:
Resulting active | active requested? | Scope changed? | Re-checked? | On breach |
|---|---|---|---|---|
true | Yes (explicit) | — | Yes | 409 RULE_ACTIVE_LIMIT_REACHED, no changes applied |
true (unchanged) | No | Yes | Yes | Rule auto-disabled; scope change still saved |
true (unchanged) | No | No | No | — |
false | — | — | No | — |
An explicit aiCheckEnabled=true counts as an explicit activation request for this table
too, even when active itself is omitted (already-active rule) — AI check requires an
active rule, so a breach in that case also returns 409 RULE_ACTIVE_LIMIT_REACHED rather
than being auto-disabled.
The same rule applies to aiCheckEnabled against the AI-check limit (auto-disabling only
aiCheckEnabled, leaving the rule active, when the breach is scope-change-caused). The
active-rule limit is checked before the AI-check limit (see createRule); a scope-change-
caused active-limit breach fully disables the rule and skips the AI-check re-check entirely,
since a disabled rule can’t be AI-check-enabled either way.
On breach caused by an explicit active=true/aiCheckEnabled=true request: 409 with
error codes RULE_ACTIVE_LIMIT_REACHED / RULE_AI_CHECK_LIMIT_REACHED (alongside
RULE_UNLINK_REQUIRES_CONFIRMATION above — both use 409 for this endpoint), and no
changes are applied. On breach caused solely by a scope change: no error — the rule is
auto-disabled as described above and the response reflects its new active/
aiCheckEnabled values.
The “All Groups” system content group
As with createRule, passing the organization’s Control Hub “All Groups” system content
group ID as the sole entry in contentGroupIds is equivalent to setting
allContentGroups=true; combining it with any other content group ID is rejected with
400 INVALID_ARGUMENT.
Activation lock
As with createRule, limit re-checks are performed under a per-organization activation
lock; if it cannot be acquired, the request fails with 503 RULE_ACTIVATION_LOCK_UNAVAILABLE
— retry the request.
curl --request PATCH \
--url https://eu.phrase.com/styleguide/api/v1/rules/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"rule": "Avoid passive voice in all user-facing content.",
"allContentGroups": true,
"contentGroupIds": [
"<string>"
],
"allLanguages": true,
"languages": [
"<string>"
],
"active": true,
"aiCheckEnabled": true,
"forceUnlink": false
}
'import requests
url = "https://eu.phrase.com/styleguide/api/v1/rules/{id}"
payload = {
"rule": "Avoid passive voice in all user-facing content.",
"allContentGroups": True,
"contentGroupIds": ["<string>"],
"allLanguages": True,
"languages": ["<string>"],
"active": True,
"aiCheckEnabled": True,
"forceUnlink": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
rule: 'Avoid passive voice in all user-facing content.',
allContentGroups: true,
contentGroupIds: ['<string>'],
allLanguages: true,
languages: ['<string>'],
active: true,
aiCheckEnabled: true,
forceUnlink: false
})
};
fetch('https://eu.phrase.com/styleguide/api/v1/rules/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://eu.phrase.com/styleguide/api/v1/rules/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'rule' => 'Avoid passive voice in all user-facing content.',
'allContentGroups' => true,
'contentGroupIds' => [
'<string>'
],
'allLanguages' => true,
'languages' => [
'<string>'
],
'active' => true,
'aiCheckEnabled' => true,
'forceUnlink' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://eu.phrase.com/styleguide/api/v1/rules/{id}"
payload := strings.NewReader("{\n \"rule\": \"Avoid passive voice in all user-facing content.\",\n \"allContentGroups\": true,\n \"contentGroupIds\": [\n \"<string>\"\n ],\n \"allLanguages\": true,\n \"languages\": [\n \"<string>\"\n ],\n \"active\": true,\n \"aiCheckEnabled\": true,\n \"forceUnlink\": false\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://eu.phrase.com/styleguide/api/v1/rules/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"rule\": \"Avoid passive voice in all user-facing content.\",\n \"allContentGroups\": true,\n \"contentGroupIds\": [\n \"<string>\"\n ],\n \"allLanguages\": true,\n \"languages\": [\n \"<string>\"\n ],\n \"active\": true,\n \"aiCheckEnabled\": true,\n \"forceUnlink\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://eu.phrase.com/styleguide/api/v1/rules/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"rule\": \"Avoid passive voice in all user-facing content.\",\n \"allContentGroups\": true,\n \"contentGroupIds\": [\n \"<string>\"\n ],\n \"allLanguages\": true,\n \"languages\": [\n \"<string>\"\n ],\n \"active\": true,\n \"aiCheckEnabled\": true,\n \"forceUnlink\": false\n}"
response = http.request(request)
puts response.read_body{
"id": "01900000-0000-7000-8000-000000000001",
"rule": "Avoid passive voice in all user-facing content.",
"active": true,
"aiCheckEnabled": true,
"allContentGroups": true,
"allLanguages": true,
"contentGroups": [
{
"id": "cg-marketing-en"
}
],
"languages": [
{
"bcpCode": "en-GB",
"description": "English (United Kingdom)",
"language": "cs",
"region": "gb",
"script": "LATN"
}
],
"createdAt": "2024-01-15T10:30:00Z",
"lastModifiedAt": "2024-06-01T14:22:00Z",
"name": "No passive voice",
"omittedReason": "<string>",
"eligibilityCheckedAt": "2024-06-01T14:22:05Z",
"styleGuide": null,
"createdBy": null,
"lastModifiedBy": null
}{
"code": "<string>",
"message": "<string>",
"detail": "<string>"
}{
"code": "<string>",
"message": "<string>",
"detail": "<string>"
}{
"code": "<string>",
"message": "<string>",
"detail": "<string>"
}{
"code": "<string>",
"message": "<string>",
"detail": "<string>"
}{
"code": "<string>",
"message": "<string>",
"detail": "<string>"
}Authorizations
JWT from IDM (Authorization: Bearer )
Path Parameters
Rule ID
Body
Request to update an existing Rule. Only fields that are present (non-null) in the JSON body are applied.
Updated rule text. Changing it would unlink the rule from its Style Guide; set forceUnlink=true to confirm, otherwise the request fails with 409 CONFLICT.
450"Avoid passive voice in all user-facing content."
When true, this rule applies to all content groups and contentGroupIds must be absent or empty. When false, contentGroupIds must be provided and non-empty. Null = no change. Any change to the content group scope of a rule linked to a Style Guide would unlink it; set forceUnlink=true to confirm, otherwise the request fails with 409 CONFLICT.
Complete replacement of the Content Group IDs this rule applies to. Null = no change. Must be non-empty when allContentGroups is false; must be absent or empty when allContentGroups is true. Any previously set IDs not included here are removed. Any change to the content group scope of a rule linked to a Style Guide would unlink it; set forceUnlink=true to confirm, otherwise the request fails with 409 CONFLICT.
10036When true, this rule applies to all languages and languages must be absent or empty. When false, languages must be provided and non-empty. Null = no change. Any change to the language scope of a rule linked to a Style Guide would unlink it; set forceUnlink=true to confirm, otherwise the request fails with 409 CONFLICT.
Complete replacement of the language codes this rule applies to. Equivalent representations such as en_US are accepted and normalised to canonical BCP-47 (en-US). Null = no change. Must be non-empty when allLanguages is false; must be absent or empty when allLanguages is true. Any previously set codes not included here are removed. Any change to the language scope of a rule linked to a Style Guide would unlink it; set forceUnlink=true to confirm, otherwise the request fails with 409 CONFLICT.
1001Whether this rule is active. Null = no change.
Whether this rule is used during AI-powered quality checks. Null = no change.
Confirms that this update may unlink the rule from its currently linked Style Guide. Required (must be true) when a change to rule text, content group scope, or language scope would cause an unlink; otherwise the request fails with 409 CONFLICT and no changes are applied. Default: false.
Response
Rule updated successfully
Rule details
Unique identifier for this Rule
"01900000-0000-7000-8000-000000000001"
The rule text
"Avoid passive voice in all user-facing content."
Whether this rule is active
Whether this rule is used during AI-powered quality checks
Whether this rule applies to all content groups
Whether this rule applies to all languages
Content Groups this rule applies to. Empty list means all content groups. Null means no content groups are assigned.
Show child attributes
Show child attributes
Language details for languages this rule applies to. Empty list means all languages. Null means no languages are assigned.
Show child attributes
Show child attributes
When this rule was created
"2024-01-15T10:30:00Z"
When this rule was last modified
"2024-06-01T14:22:00Z"
A short, system-generated name indicating this rule's purpose. Never user-entered; automatically generated, so it may be absent shortly after the rule is created.
"No passive voice"
Reason this rule is omitted from AI checks, as determined by an automated eligibility check. Absent if the rule is eligible, or if the check hasn't completed yet.
When the automated AI-check eligibility check last completed for this rule. Null means it hasn't run yet: eligibility is still pending, so a client should treat the AI-check state as 'checking' rather than eligible. Once set, a null omittedReason means eligible and a non-null omittedReason means omitted.
"2024-06-01T14:22:05Z"
Style Guide this rule was extracted from. Null when the rule is unlinked — either manually created or subsequently edited.
User who created this rule
User who last modified this rule
Was this page helpful?