curl --request PATCH \
--url https://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles/{profile_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"devin_mcp_read_only": true,
"mcp_config": {
"servers": [
"<string>"
]
},
"name": "<string>",
"net_policy": {
"allow": [
{
"hostname": "<string>"
}
]
},
"remove_github_cli_token": true,
"slack_channel_access": {
"channels": [
{
"channel_id": "<string>",
"team_id": "<string>"
}
]
},
"teams_channel_access": {
"channels": [
{
"channel_id": "<string>",
"team_id": "<string>"
}
]
}
}
'import requests
url = "https://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles/{profile_id}"
payload = {
"devin_mcp_read_only": True,
"mcp_config": { "servers": ["<string>"] },
"name": "<string>",
"net_policy": { "allow": [{ "hostname": "<string>" }] },
"remove_github_cli_token": True,
"slack_channel_access": { "channels": [
{
"channel_id": "<string>",
"team_id": "<string>"
}
] },
"teams_channel_access": { "channels": [
{
"channel_id": "<string>",
"team_id": "<string>"
}
] }
}
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({
devin_mcp_read_only: true,
mcp_config: {servers: ['<string>']},
name: '<string>',
net_policy: {allow: [{hostname: '<string>'}]},
remove_github_cli_token: true,
slack_channel_access: {channels: [{channel_id: '<string>', team_id: '<string>'}]},
teams_channel_access: {channels: [{channel_id: '<string>', team_id: '<string>'}]}
})
};
fetch('https://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles/{profile_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://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles/{profile_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([
'devin_mcp_read_only' => true,
'mcp_config' => [
'servers' => [
'<string>'
]
],
'name' => '<string>',
'net_policy' => [
'allow' => [
[
'hostname' => '<string>'
]
]
],
'remove_github_cli_token' => true,
'slack_channel_access' => [
'channels' => [
[
'channel_id' => '<string>',
'team_id' => '<string>'
]
]
],
'teams_channel_access' => [
'channels' => [
[
'channel_id' => '<string>',
'team_id' => '<string>'
]
]
]
]),
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://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles/{profile_id}"
payload := strings.NewReader("{\n \"devin_mcp_read_only\": true,\n \"mcp_config\": {\n \"servers\": [\n \"<string>\"\n ]\n },\n \"name\": \"<string>\",\n \"net_policy\": {\n \"allow\": [\n {\n \"hostname\": \"<string>\"\n }\n ]\n },\n \"remove_github_cli_token\": true,\n \"slack_channel_access\": {\n \"channels\": [\n {\n \"channel_id\": \"<string>\",\n \"team_id\": \"<string>\"\n }\n ]\n },\n \"teams_channel_access\": {\n \"channels\": [\n {\n \"channel_id\": \"<string>\",\n \"team_id\": \"<string>\"\n }\n ]\n }\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://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles/{profile_id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"devin_mcp_read_only\": true,\n \"mcp_config\": {\n \"servers\": [\n \"<string>\"\n ]\n },\n \"name\": \"<string>\",\n \"net_policy\": {\n \"allow\": [\n {\n \"hostname\": \"<string>\"\n }\n ]\n },\n \"remove_github_cli_token\": true,\n \"slack_channel_access\": {\n \"channels\": [\n {\n \"channel_id\": \"<string>\",\n \"team_id\": \"<string>\"\n }\n ]\n },\n \"teams_channel_access\": {\n \"channels\": [\n {\n \"channel_id\": \"<string>\",\n \"team_id\": \"<string>\"\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles/{profile_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 \"devin_mcp_read_only\": true,\n \"mcp_config\": {\n \"servers\": [\n \"<string>\"\n ]\n },\n \"name\": \"<string>\",\n \"net_policy\": {\n \"allow\": [\n {\n \"hostname\": \"<string>\"\n }\n ]\n },\n \"remove_github_cli_token\": true,\n \"slack_channel_access\": {\n \"channels\": [\n {\n \"channel_id\": \"<string>\",\n \"team_id\": \"<string>\"\n }\n ]\n },\n \"teams_channel_access\": {\n \"channels\": [\n {\n \"channel_id\": \"<string>\",\n \"team_id\": \"<string>\"\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"created_at": 123,
"devin_mcp_read_only": true,
"enforcement_level": "recommended",
"git_access_level": "read_only",
"name": "<string>",
"org_id": "<string>",
"profile_id": "<string>",
"remove_github_cli_token": true,
"updated_at": 123,
"mcp_config": {
"servers": [
"<string>"
]
},
"net_policy": {
"allow": [
{
"hostname": "<string>"
}
]
},
"slack_channel_access": {
"mode": "none",
"channels": [
{
"channel_id": "<string>",
"team_id": "<string>"
}
]
},
"slack_dm_scope": "disabled",
"teams_channel_access": {
"mode": "none",
"channels": [
{
"channel_id": "<string>",
"team_id": "<string>"
}
]
},
"teams_dm_scope": "disabled",
"teams_group_chat_scope": "disabled"
}{
"status": 123,
"title": "<string>",
"detail": "<string>",
"error_code": "<string>",
"errors": [
{}
],
"instance": "<string>",
"type": "about:blank"
}{
"status": 123,
"title": "<string>",
"detail": "<string>",
"error_code": "<string>",
"errors": [
{}
],
"instance": "<string>",
"type": "about:blank"
}{
"status": 123,
"title": "<string>",
"detail": "<string>",
"error_code": "<string>",
"errors": [
{}
],
"instance": "<string>",
"type": "about:blank"
}{
"status": 123,
"title": "<string>",
"detail": "<string>",
"error_code": "<string>",
"errors": [
{}
],
"instance": "<string>",
"type": "about:blank"
}{
"status": 123,
"title": "<string>",
"detail": "<string>",
"error_code": "<string>",
"errors": [
{}
],
"instance": "<string>",
"type": "about:blank"
}{
"status": 123,
"title": "<string>",
"detail": "<string>",
"error_code": "<string>",
"errors": [
{}
],
"instance": "<string>",
"type": "about:blank"
}Update an org security profile
Update an organization-owned security profile. Omitted fields are left unchanged; explicit null clears net_policy / mcp_config.
curl --request PATCH \
--url https://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles/{profile_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"devin_mcp_read_only": true,
"mcp_config": {
"servers": [
"<string>"
]
},
"name": "<string>",
"net_policy": {
"allow": [
{
"hostname": "<string>"
}
]
},
"remove_github_cli_token": true,
"slack_channel_access": {
"channels": [
{
"channel_id": "<string>",
"team_id": "<string>"
}
]
},
"teams_channel_access": {
"channels": [
{
"channel_id": "<string>",
"team_id": "<string>"
}
]
}
}
'import requests
url = "https://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles/{profile_id}"
payload = {
"devin_mcp_read_only": True,
"mcp_config": { "servers": ["<string>"] },
"name": "<string>",
"net_policy": { "allow": [{ "hostname": "<string>" }] },
"remove_github_cli_token": True,
"slack_channel_access": { "channels": [
{
"channel_id": "<string>",
"team_id": "<string>"
}
] },
"teams_channel_access": { "channels": [
{
"channel_id": "<string>",
"team_id": "<string>"
}
] }
}
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({
devin_mcp_read_only: true,
mcp_config: {servers: ['<string>']},
name: '<string>',
net_policy: {allow: [{hostname: '<string>'}]},
remove_github_cli_token: true,
slack_channel_access: {channels: [{channel_id: '<string>', team_id: '<string>'}]},
teams_channel_access: {channels: [{channel_id: '<string>', team_id: '<string>'}]}
})
};
fetch('https://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles/{profile_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://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles/{profile_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([
'devin_mcp_read_only' => true,
'mcp_config' => [
'servers' => [
'<string>'
]
],
'name' => '<string>',
'net_policy' => [
'allow' => [
[
'hostname' => '<string>'
]
]
],
'remove_github_cli_token' => true,
'slack_channel_access' => [
'channels' => [
[
'channel_id' => '<string>',
'team_id' => '<string>'
]
]
],
'teams_channel_access' => [
'channels' => [
[
'channel_id' => '<string>',
'team_id' => '<string>'
]
]
]
]),
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://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles/{profile_id}"
payload := strings.NewReader("{\n \"devin_mcp_read_only\": true,\n \"mcp_config\": {\n \"servers\": [\n \"<string>\"\n ]\n },\n \"name\": \"<string>\",\n \"net_policy\": {\n \"allow\": [\n {\n \"hostname\": \"<string>\"\n }\n ]\n },\n \"remove_github_cli_token\": true,\n \"slack_channel_access\": {\n \"channels\": [\n {\n \"channel_id\": \"<string>\",\n \"team_id\": \"<string>\"\n }\n ]\n },\n \"teams_channel_access\": {\n \"channels\": [\n {\n \"channel_id\": \"<string>\",\n \"team_id\": \"<string>\"\n }\n ]\n }\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://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles/{profile_id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"devin_mcp_read_only\": true,\n \"mcp_config\": {\n \"servers\": [\n \"<string>\"\n ]\n },\n \"name\": \"<string>\",\n \"net_policy\": {\n \"allow\": [\n {\n \"hostname\": \"<string>\"\n }\n ]\n },\n \"remove_github_cli_token\": true,\n \"slack_channel_access\": {\n \"channels\": [\n {\n \"channel_id\": \"<string>\",\n \"team_id\": \"<string>\"\n }\n ]\n },\n \"teams_channel_access\": {\n \"channels\": [\n {\n \"channel_id\": \"<string>\",\n \"team_id\": \"<string>\"\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles/{profile_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 \"devin_mcp_read_only\": true,\n \"mcp_config\": {\n \"servers\": [\n \"<string>\"\n ]\n },\n \"name\": \"<string>\",\n \"net_policy\": {\n \"allow\": [\n {\n \"hostname\": \"<string>\"\n }\n ]\n },\n \"remove_github_cli_token\": true,\n \"slack_channel_access\": {\n \"channels\": [\n {\n \"channel_id\": \"<string>\",\n \"team_id\": \"<string>\"\n }\n ]\n },\n \"teams_channel_access\": {\n \"channels\": [\n {\n \"channel_id\": \"<string>\",\n \"team_id\": \"<string>\"\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"created_at": 123,
"devin_mcp_read_only": true,
"enforcement_level": "recommended",
"git_access_level": "read_only",
"name": "<string>",
"org_id": "<string>",
"profile_id": "<string>",
"remove_github_cli_token": true,
"updated_at": 123,
"mcp_config": {
"servers": [
"<string>"
]
},
"net_policy": {
"allow": [
{
"hostname": "<string>"
}
]
},
"slack_channel_access": {
"mode": "none",
"channels": [
{
"channel_id": "<string>",
"team_id": "<string>"
}
]
},
"slack_dm_scope": "disabled",
"teams_channel_access": {
"mode": "none",
"channels": [
{
"channel_id": "<string>",
"team_id": "<string>"
}
]
},
"teams_dm_scope": "disabled",
"teams_group_chat_scope": "disabled"
}{
"status": 123,
"title": "<string>",
"detail": "<string>",
"error_code": "<string>",
"errors": [
{}
],
"instance": "<string>",
"type": "about:blank"
}{
"status": 123,
"title": "<string>",
"detail": "<string>",
"error_code": "<string>",
"errors": [
{}
],
"instance": "<string>",
"type": "about:blank"
}{
"status": 123,
"title": "<string>",
"detail": "<string>",
"error_code": "<string>",
"errors": [
{}
],
"instance": "<string>",
"type": "about:blank"
}{
"status": 123,
"title": "<string>",
"detail": "<string>",
"error_code": "<string>",
"errors": [
{}
],
"instance": "<string>",
"type": "about:blank"
}{
"status": 123,
"title": "<string>",
"detail": "<string>",
"error_code": "<string>",
"errors": [
{}
],
"instance": "<string>",
"type": "about:blank"
}{
"status": 123,
"title": "<string>",
"detail": "<string>",
"error_code": "<string>",
"errors": [
{}
],
"instance": "<string>",
"type": "about:blank"
}Permissions
Requires a service user or personal access token with theManageSecureModeProfiles permission at the organization level. Tokens used by a running Devin session are rejected, so a session cannot change the profiles that govern it.
Behavior
- Omitted fields are left unchanged.
- An explicit
nullclears the profile’s opinion fornet_policy,mcp_config,slack_channel_access,slack_dm_scope,teams_channel_access,teams_dm_scope, andteams_group_chat_scope.nullis rejected for the other fields. net_policy: nullmeans the profile has no network opinion, not deny-all. Use{"allow": []}for deny-all.mcp_config.serverslists MCP servers by slug (a marketplace slug such asgithub, or an installation’s slug).
Authorizations
Service User credential (prefix: cog_)
Path Parameters
Organization ID (prefix: org-)
"org-abc123def456"
Body
PATCH semantics: omitted fields are left unchanged; explicit null clears the nullable fields (net_policy, mcp_config, slack_channel_access, slack_dm_scope, teams_channel_access, teams_dm_scope, teams_group_chat_scope) and is rejected for the others.
recommended, mandatory read_only, read_write Show child attributes
Show child attributes
1 - 128Show child attributes
Show child attributes
Show child attributes
Show child attributes
disabled, org_members, workspace Show child attributes
Show child attributes
disabled, installed_users disabled, origin_chat Response
Successful Response
An organization-owned security profile.
When true, sessions may only call read-only Devin MCP tools (no session creation, automation management, or other write operations).
recommended profiles can be overridden by descendant bindings; mandatory profiles are a floor that descendant policies only narrow.
recommended, mandatory read_only, read_write The security profile's ID.
When true, the GitHub CLI token is removed from the session's machine, preventing direct GitHub API access.
null = this profile has no MCP opinion.
Show child attributes
Show child attributes
null = this profile has no network opinion (it does NOT mean deny-all).
Show child attributes
Show child attributes
Ceiling on the Slack channels sessions governed by this profile may read and post in. null = this profile has no opinion and the organization's Slack setting applies.
Show child attributes
Show child attributes
Ceiling on who may DM Devin in Slack under this profile. null = this profile has no opinion and the organization's Slack setting applies. 'workspace' is narrowed to 'org_members' for enterprise accounts.
disabled, org_members, workspace Ceiling on the Microsoft Teams channels sessions governed by this profile may read and post in. null = this profile has no opinion and the organization's Teams Default Access applies.
Show child attributes
Show child attributes
Ceiling on who Devin may DM in Microsoft Teams under this profile. null = this profile has no opinion and the organization's Teams Default Access applies.
disabled, installed_users Ceiling on which Teams group chats Devin may read under this profile; origin_chat = only the group chat the session was started from; null = no opinion, derived from the org's Teams Default Access like DMs.
disabled, origin_chat 
