curl --request POST \
--url https://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"devin_mcp_read_only": false,
"enforcement_level": "recommended",
"git_access_level": "read_write",
"mcp_config": {
"servers": [
"<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"
payload = {
"name": "<string>",
"devin_mcp_read_only": False,
"enforcement_level": "recommended",
"git_access_level": "read_write",
"mcp_config": { "servers": ["<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.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
devin_mcp_read_only: false,
enforcement_level: 'recommended',
git_access_level: 'read_write',
mcp_config: {servers: ['<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', 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",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'devin_mcp_read_only' => false,
'enforcement_level' => 'recommended',
'git_access_level' => 'read_write',
'mcp_config' => [
'servers' => [
'<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"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"devin_mcp_read_only\": false,\n \"enforcement_level\": \"recommended\",\n \"git_access_level\": \"read_write\",\n \"mcp_config\": {\n \"servers\": [\n \"<string>\"\n ]\n },\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("POST", 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.post("https://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"devin_mcp_read_only\": false,\n \"enforcement_level\": \"recommended\",\n \"git_access_level\": \"read_write\",\n \"mcp_config\": {\n \"servers\": [\n \"<string>\"\n ]\n },\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")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"devin_mcp_read_only\": false,\n \"enforcement_level\": \"recommended\",\n \"git_access_level\": \"read_write\",\n \"mcp_config\": {\n \"servers\": [\n \"<string>\"\n ]\n },\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"
}Create an org security profile
Create an organization-owned security profile.
curl --request POST \
--url https://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"devin_mcp_read_only": false,
"enforcement_level": "recommended",
"git_access_level": "read_write",
"mcp_config": {
"servers": [
"<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"
payload = {
"name": "<string>",
"devin_mcp_read_only": False,
"enforcement_level": "recommended",
"git_access_level": "read_write",
"mcp_config": { "servers": ["<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.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
devin_mcp_read_only: false,
enforcement_level: 'recommended',
git_access_level: 'read_write',
mcp_config: {servers: ['<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', 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",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'devin_mcp_read_only' => false,
'enforcement_level' => 'recommended',
'git_access_level' => 'read_write',
'mcp_config' => [
'servers' => [
'<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"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"devin_mcp_read_only\": false,\n \"enforcement_level\": \"recommended\",\n \"git_access_level\": \"read_write\",\n \"mcp_config\": {\n \"servers\": [\n \"<string>\"\n ]\n },\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("POST", 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.post("https://api.devin.ai/v3beta1/organizations/{org_id}/security-profiles")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"devin_mcp_read_only\": false,\n \"enforcement_level\": \"recommended\",\n \"git_access_level\": \"read_write\",\n \"mcp_config\": {\n \"servers\": [\n \"<string>\"\n ]\n },\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")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"devin_mcp_read_only\": false,\n \"enforcement_level\": \"recommended\",\n \"git_access_level\": \"read_write\",\n \"mcp_config\": {\n \"servers\": [\n \"<string>\"\n ]\n },\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
- Only
nameis required. Profile names must be unique within the organization. - When
net_policyis omitted, the profile starts from an allowlist containing only the git integration host (the same starting point as the settings page). An explicitnullmeans the profile has no network opinion, not deny-all. remove_github_cli_tokendefaults totrue. Keeping the token (false) requiresgit_access_level: read_writeand, when a network policy is set, an allowlist that includesapi.github.com.git_access_leveldefaults toread_writeandenforcement_leveltorecommended.
Authorizations
Service User credential (prefix: cog_)
Path Parameters
Organization ID (prefix: org-)
"org-abc123def456"
Body
1 - 128recommended, mandatory read_only, read_write Show child attributes
Show child attributes
Omitted = an allow list containing only the git integration host (the same default the Security Profiles UI starts from); explicit null = this profile has no network opinion (it does NOT mean deny-all). Because the default allow list does not include api.github.com, a request with remove_github_cli_token=false must supply net_policy explicitly (or null).
Show child attributes
Show child attributes
Omitted or null = this profile has no Slack channel opinion (the organization's Slack setting applies).
Show child attributes
Show child attributes
Omitted or null = this profile has no Slack DM opinion (the organization's Slack setting applies).
disabled, org_members, workspace Omitted or null = this profile has no Teams channel opinion (the organization's Teams Default Access applies).
Show child attributes
Show child attributes
Omitted or null = this profile has no Teams DM opinion (the organization's Teams Default Access applies).
disabled, installed_users Omitted or null = this profile has no Teams group-chat opinion (derived from the organization's Teams Default Access like DMs).
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 
