Update Policy Group
Endpoint
PUT /apiops/projects/{projectName}/policyGroups/{policyGroupName}/
Authentication
Requires a Personal API Access Token.
Header
Authorization: Bearer YOUR_TOKEN
Request
Headers
| Header | Value | Required |
|---|---|---|
| Authorization | Bearer {token} | Yes |
| Content-Type | application/json | Yes |
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| projectName | string | Yes | Project name |
| policyGroupName | string | Yes | Policy group name (the group must already exist) |
Query Parameters
None
Request Body
The body is bound directly to the PolicyGroup model, which inherits the same "_class"
polymorphic discriminator as Global Policies — include
"_class": "policy-group" as in Create Policy Group
to avoid a deserialization error. If "name" is omitted from the body it falls back to the
policyGroupName path variable; if present it must match (case-insensitive).
Full JSON Body Example
{
"_class": "policy-group",
"name": "standard-security-bundle",
"description": "IP allow-list applied before authentication (rotated)",
"active": true,
"targetPipeline": "REQUEST",
"order": 1,
"makeDefault": false,
"canBeDeleted": true,
"policyList": [
{
"_class": "ip-white",
"name": "office-network-allow-list",
"active": true,
"useApinizerDefault": false,
"ipList": ["203.0.113.0/24", "198.51.100.11"]
}
]
}
Request Body Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| _class | string | Yes | - | Must be "policy-group" |
| name | string | No | path variable | Policy group name — if present must match the policyGroupName path variable |
| description | string | No | - | Policy group description |
| active | boolean | No | false | Whether the group is active |
| targetPipeline | string | No | - | Pipeline the group is bound to: REQUEST, RESPONSE or ERROR |
| order | integer | No | - | Execution order among other policies/groups on the same pipeline |
| makeDefault | boolean | No | - | Whether this group is applied by default |
| canBeDeleted | boolean | No | - | Deletion-eligibility flag used by the classic UI |
| policyList | array | No | [] | Ordered list of embedded policies, each a polymorphic Policy snapshot (own _class); replaces the stored list entirely |
id is always preserved from the existing record and projectId is always taken from the resolved
project — both are ignored if present in the body. global stays false, same as create.
Secret Contract (POST vs PUT)
Unlike Create Policy Group (which accepts
pre-encrypted, cross-instance snapshots), PUT is the normal human-authored update path:
@SecretDatafields on embedded policies inpolicyList(e.g.passwordon an embedded WS-Security Username Token policy) must be sent plaintext. They are encrypted before the record is persisted.- There is no blank-preserves-stored-value behavior. Because
Get Policy Group and
List Policy Groups never return the embedded
policy list, you must resupply the full, correct
policyList— including plaintext secrets for any secret-bearing embedded policy type — on every update. - Unlike Create Policy Group,
PUTdoes not rebind embedded global policy references to this instance's definitions; it persistspolicyListexactly as given.
Notes
- The group identified by
policyGroupNamemust already exist, otherwise a400is returned. policyListis replaced wholesale — this is not a partial/merge update. Omit an embedded policy you intend to keep and it is removed from the group.- If
nameis present in the body it must match thepolicyGroupNamepath variable (case-insensitive).
Response
Success Response (200 OK)
{
"status": "SUCCESS",
"resultList": [
{
"id": "665f2a1c9b3e4a0012ab35aa",
"name": "standard-security-bundle",
"targetPipeline": "REQUEST"
}
],
"resultCount": 1
}
Response Fields
| Field | Type | Description |
|---|---|---|
| status | string | Response status: SUCCESS or FAILURE |
| resultList | array | Single-element list containing the updated policy group's descriptor |
| resultCount | integer | Always 1 on success |
Error Response (400 Bad Request)
{
"status": "FAILURE",
"resultMessage": "Policy group (name: standard-security-bundle) was not found!"
}
or
{
"status": "FAILURE",
"resultMessage": "Policy group name in path (standard-security-bundle) does not match name in body (standard-security-bundle-2)!"
}
Error Response (401 Unauthorized)
{
"status": "FAILURE",
"resultMessage": "Token is not valid!"
}
cURL Example
curl -X PUT \
"https://demo.apinizer.com/apiops/projects/MyProject/policyGroups/standard-security-bundle/" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"_class": "policy-group",
"name": "standard-security-bundle",
"description": "IP allow-list applied before authentication (rotated)",
"active": true,
"targetPipeline": "REQUEST",
"order": 1,
"policyList": [
{
"_class": "ip-white",
"name": "office-network-allow-list",
"active": true,
"useApinizerDefault": false,
"ipList": ["203.0.113.0/24", "198.51.100.11"]
}
]
}'
Notes and Warnings
- Update-Only: Unlike Create Policy Group,
PUTfails with a400when the named group does not exist. - Plaintext Secret Contract: Embedded policy
@SecretDatafields must be sent plaintext and are encrypted before persist — the opposite of whatPOSTexpects. See Secret Contract above. - Whole-List Replace:
policyListis not merged — it fully replaces the stored embedded policy list. - Cascades and Redeploys: The updated group is pushed into every API proxy and API proxy group that embeds it by id, and is redeployed to every running environment it is already deployed to — unlike Create Policy Group, which only persists.
- Permission: Requires
API_MANAGEMENT+MANAGEin the project.
Related Documentation
- Create Policy Group - Create a new policy group (pre-encrypted snapshot contract)
- Get Policy Group - Read a policy group's descriptor back
- Delete Policy Group - Delete a policy group
- Policy Groups API - Resource overview
- Authentication Guide - How to obtain and use API tokens
- Error Handling - Error response formats