Update a Holdout using JSON Patch
1 min
POST
https://api.optimizely.com/flags/v1//projects/{project_id}/holdouts/{holdout_id}
Path Parameters
- project_idintegerrequiredExampleDescription
- holdout_idintegerrequiredExampleDescription
Responses
200
- HoldoutMapExamplesUpdated holdout with new name and traffic:
{ "987": { "archive_url": "/projects/12345/holdouts/archived", "archived": false, "created_time": "2019-05-08T00:00:00.000Z", "delete_url": "/projects/12345/holdouts/987", "description": "Updated control group for better targeting", "environment_key": "production", "holdout_results_api_token": "SampleToken.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9", "id": 987, "name": "Updated Control Group", "project_id": 12345, "rules": { "456": { "created_time": "2022-01-08T00:00:00.000Z", "flag_key": "recurring_revenue", "flag_name": "Recurring Revenue", "flag_status": "unarchived", "rule_key": "experiment_one", "rule_name": "Experiment One", "traffic_allocation": 2000, "updated_time": "2022-01-08T00:00:00.000Z" } }, "status": "draft", "traffic_allocation": 2500, "unarchive_url": "/projects/12345/holdouts/unarchived", "update_url": "/projects/12345/holdouts/987", "updated_time": "2024-09-16T10:30:00.000Z", "url": "/projects/12345/holdouts/987", "urn": "holdouts.flag.optimizely.com::987" } }Holdout moved to running status:{ "987": { "archived": false, "created_time": "2019-05-08T00:00:00.000Z", "delete_url": "/projects/12345/holdouts/987", "description": "Now actively excluding traffic from experiments", "environment_key": "production", "holdout_results_api_token": "SampleToken.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9", "id": 987, "name": "Live Control Group", "project_id": 12345, "start_time": "2024-09-16T10:30:00.000Z", "status": "running", "traffic_allocation": 1500, "update_url": "/projects/12345/holdouts/987", "updated_time": "2024-09-16T10:30:00.000Z", "url": "/projects/12345/holdouts/987", "urn": "holdouts.flag.optimizely.com::987" } }Description
400
- ProblemDetailExamplesLimited updates on concluded holdout:
{ "detail": "Can't edit holdouts in 'concluded' state.", "status": 400, "title": "Unable to update holdout", "type": "about:blank" }Invalid status transition:{ "detail": "Holdout with key 'control_group' is not in 'draft' state, can't move to 'running' state.", "status": 400, "title": "Unable to update holdout", "type": "about:blank" }Traffic allocation out of range:{ "detail": "Traffic allocation must be between 0 and 10000 (basis points).", "status": 400, "title": "Unable to update holdout", "type": "about:blank" }Cannot update metrics on running holdout:{ "detail": "Can't update metrics on a running holdout.", "status": 400, "title": "Unable to update holdout", "type": "about:blank" }Description- detailstringrequiredDescription
- statusintegerrequiredDescription
- titlestringrequiredDescription
- typestringrequiredDescription
- uuidstringDescription
401
403
404
409
curl
curl --request POST \
--url https://api.optimizely.com/flags/v1//projects/{project_id}/holdouts/{holdout_id} \
--header 'accept: application/json'javascript
var myHeaders = new Headers();
myHeaders.append("accept", "application/json");
myHeaders.append("content-type", "application/json-patch+json");
var requestOptions = {
method: 'POST',
headers: myHeaders,
redirect: 'follow'
};
fetch("https://api.optimizely.com/flags/v1//projects/{project_id}/holdouts/{holdout_id}", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));ruby
require "uri"
require "json"
require "net/http"
url = URI("https://api.optimizely.com/flags/v1//projects/{project_id}/holdouts/{holdout_id}")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["accept"] = "application/json"
request["content-type"] = "application/json-patch+json"
response = https.request(request)
puts response.read_body
python
import requests
import json
url = "https://api.optimizely.com/flags/v1//projects/{project_id}/holdouts/{holdout_id}"
payload = {}
headers = {
'accept': 'application/json',
'content-type': 'application/json-patch+json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
200
// Successful update of the holdout. Returns the updated holdout resource with all modifications applied.
Response Details:
Contains the complete updated holdout with all applied changes
Includes RESTful JSON (https://restfuljson.org/) styled links for related actions
Automatic timestamps are included (start_time/end_time) if status was changed
Missing links indicate insufficient permissions for related operations
ReadOnly fields reflect any server-managed updates (like timestamps)
Status-Specific Behavior:
Draft→Running: Includes newly set start_time
Running→Concluded: Includes newly set end_time
Archived: Shows archived: true with preserved historical data
{}GENERATED
// Successful update of the holdout. Returns the updated holdout resource with all modifications applied.
Response Details:
Contains the complete updated holdout with all applied changes
Includes RESTful JSON (https://restfuljson.org/) styled links for related actions
Automatic timestamps are included (start_time/end_time) if status was changed
Missing links indicate insufficient permissions for related operations
ReadOnly fields reflect any server-managed updates (like timestamps)
Status-Specific Behavior:
Draft→Running: Includes newly set start_time
Running→Concluded: Includes newly set end_time
Archived: Shows archived: true with preserved historical data
{}basic_update
// Updated holdout with new name and traffic
{
"987": {
"archive_url": "/projects/12345/holdouts/archived",
"archived": false,
"created_time": "2019-05-08T00:00:00.000Z",
"delete_url": "/projects/12345/holdouts/987",
"description": "Updated control group for better targeting",
"environment_key": "production",
"holdout_results_api_token": "SampleToken.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
"id": 987,
"name": "Updated Control Group",
"project_id": 12345,
"rules": {
"456": {
"created_time": "2022-01-08T00:00:00.000Z",
"flag_key": "recurring_revenue",
"flag_name": "Recurring Revenue",
"flag_status": "unarchived",
"rule_key": "experiment_one",
"rule_name": "Experiment One",
"traffic_allocation": 2000,
"updated_time": "2022-01-08T00:00:00.000Z"
}
},
"status": "draft",
"traffic_allocation": 2500,
"unarchive_url": "/projects/12345/holdouts/unarchived",
"update_url": "/projects/12345/holdouts/987",
"updated_time": "2024-09-16T10:30:00.000Z",
"url": "/projects/12345/holdouts/987",
"urn": "holdouts.flag.optimizely.com::987"
}
}started_holdout
// Holdout moved to running status
{
"987": {
"archived": false,
"created_time": "2019-05-08T00:00:00.000Z",
"delete_url": "/projects/12345/holdouts/987",
"description": "Now actively excluding traffic from experiments",
"environment_key": "production",
"holdout_results_api_token": "SampleToken.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9",
"id": 987,
"name": "Live Control Group",
"project_id": 12345,
"start_time": "2024-09-16T10:30:00.000Z",
"status": "running",
"traffic_allocation": 1500,
"update_url": "/projects/12345/holdouts/987",
"updated_time": "2024-09-16T10:30:00.000Z",
"url": "/projects/12345/holdouts/987",
"urn": "holdouts.flag.optimizely.com::987"
}
}400
// Bad Request - Invalid patch operations, validation failures, or illegal state transitions.
Common causes:
Invalid state transitions: Attempting invalid status changes (e.g., draft→concluded)
Restricted updates: Trying to modify metrics on running holdouts
Invalid traffic allocation: Values outside 0-10000 range
Archive violations: Attempting to archive non-concluded holdouts
Malformed patch: Invalid JSON Patch structure or unsupported operations
Missing required fields: Patch operations targeting required fields with null/empty values
Type mismatches: Providing wrong data types for specific fields
{
"detail": "",
"status": 0,
"title": "",
"type": "",
"uuid": ""
}GENERATED
// Bad Request - Invalid patch operations, validation failures, or illegal state transitions.
Common causes:
Invalid state transitions: Attempting invalid status changes (e.g., draft→concluded)
Restricted updates: Trying to modify metrics on running holdouts
Invalid traffic allocation: Values outside 0-10000 range
Archive violations: Attempting to archive non-concluded holdouts
Malformed patch: Invalid JSON Patch structure or unsupported operations
Missing required fields: Patch operations targeting required fields with null/empty values
Type mismatches: Providing wrong data types for specific fields
{
"detail": "",
"status": 0,
"title": "",
"type": "",
"uuid": ""
}concluded_holdout_restriction
// Limited updates on concluded holdout
{
"detail": "Can't edit holdouts in 'concluded' state.",
"status": 400,
"title": "Unable to update holdout",
"type": "about:blank"
}invalid_state_transition
// Invalid status transition
{
"detail": "Holdout with key 'control_group' is not in 'draft' state, can't move to 'running' state.",
"status": 400,
"title": "Unable to update holdout",
"type": "about:blank"
}invalid_traffic_allocation
// Traffic allocation out of range
{
"detail": "Traffic allocation must be between 0 and 10000 (basis points).",
"status": 400,
"title": "Unable to update holdout",
"type": "about:blank"
}metrics_update_restricted
// Cannot update metrics on running holdout
{
"detail": "Can't update metrics on a running holdout.",
"status": 400,
"title": "Unable to update holdout",
"type": "about:blank"
}401
// Invalid credentials
403
// Do not have permission to perform the operation
404
// Not found. No content
409
// Conflicting resource state with requested action