curl --request PATCH \
--url https://api.ctrl-hub.com/v3/security-settings/{security_settings_id} \
--header 'Content-Type: application/vnd.api+json' \
--header 'X-Session-Token: <api-key>' \
--data '
{
"data": {
"type": "security-settings",
"attributes": {
"require_mfa": true
}
}
}
'import requests
url = "https://api.ctrl-hub.com/v3/security-settings/{security_settings_id}"
payload = { "data": {
"type": "security-settings",
"attributes": { "require_mfa": True }
} }
headers = {
"X-Session-Token": "<api-key>",
"Content-Type": "application/vnd.api+json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {'X-Session-Token': '<api-key>', 'Content-Type': 'application/vnd.api+json'},
body: JSON.stringify({data: {type: 'security-settings', attributes: {require_mfa: true}}})
};
fetch('https://api.ctrl-hub.com/v3/security-settings/{security_settings_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.ctrl-hub.com/v3/security-settings/{security_settings_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([
'data' => [
'type' => 'security-settings',
'attributes' => [
'require_mfa' => true
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/vnd.api+json",
"X-Session-Token: <api-key>"
],
]);
$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.ctrl-hub.com/v3/security-settings/{security_settings_id}"
payload := strings.NewReader("{\n \"data\": {\n \"type\": \"security-settings\",\n \"attributes\": {\n \"require_mfa\": true\n }\n }\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("X-Session-Token", "<api-key>")
req.Header.Add("Content-Type", "application/vnd.api+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.ctrl-hub.com/v3/security-settings/{security_settings_id}")
.header("X-Session-Token", "<api-key>")
.header("Content-Type", "application/vnd.api+json")
.body("{\n \"data\": {\n \"type\": \"security-settings\",\n \"attributes\": {\n \"require_mfa\": true\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ctrl-hub.com/v3/security-settings/{security_settings_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["X-Session-Token"] = '<api-key>'
request["Content-Type"] = 'application/vnd.api+json'
request.body = "{\n \"data\": {\n \"type\": \"security-settings\",\n \"attributes\": {\n \"require_mfa\": true\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "security-settings",
"attributes": {
"require_mfa": true
},
"relationships": {
"organisation": {
"data": {
"type": "organisations",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}
}
},
"jsonapi": {
"version": "1.0"
}
}{
"id": "98ca4a78-b66f-4234-9719-aaf832ee6669",
"status": "400",
"title": "A validation error was encountered",
"source": {
"parameter": "include"
},
"meta": {
"resource": "wrong_value"
}
}{
"id": "05fc9c8d-73b9-4697-9337-57f7a567a48f",
"status": "401",
"title": "You are not authorised to access this resource",
"detail": "In order to access this resource, you need the 'admin' role.",
"code": "AUTH.001"
}{
"errors": [
{
"id": "1b3f2c30-2d56-4d3a-9c44-9be9c2cbf2f0",
"status": "403",
"title": "Forbidden",
"detail": "You do not hold the grant required for this action.",
"code": "AUTH.002"
}
]
}{
"id": "7b4c8f12-3e9a-4d5b-8c6f-1a2b3c4d5e6f",
"status": "404",
"title": "Resource not found",
"detail": "The requested resource could not be found or does not exist.",
"code": "NOT_FOUND.001"
}{
"id": "fe9d9a69-f0a7-4fdc-bb2c-176027f316c5",
"status": "500",
"title": "Internal Server Error",
"detail": "An unexpected error occurred on the server."
}Update security settings
Update an organisation’s security settings. They are identified by the organisation’s id.
require_mfa makes the organisation require a second factor. While it is on,
anyone whose session is neither two-factor (aal2) nor a SAML single sign-on
sign-in cannot see the organisation’s data until they set up and use a second
factor: its members, and people working in it through a grant without being
members, such as contractors. Other OIDC sign-ins do not count. Service
accounts are exempt. It is off by default.
A change applies straight away for requests served by the same server, and within about 30 seconds everywhere else.
Turning require_mfa on is refused with 403 unless the caller’s own session
already satisfies it, so an administrator cannot lock themselves out.
Turning it off has no such check.
Only an interactive sign-in can turn it on: a person using a second factor or SAML single sign-on. A service account or other OAuth2 client has no sign-in session, so it can turn the requirement off but never on.
curl --request PATCH \
--url https://api.ctrl-hub.com/v3/security-settings/{security_settings_id} \
--header 'Content-Type: application/vnd.api+json' \
--header 'X-Session-Token: <api-key>' \
--data '
{
"data": {
"type": "security-settings",
"attributes": {
"require_mfa": true
}
}
}
'import requests
url = "https://api.ctrl-hub.com/v3/security-settings/{security_settings_id}"
payload = { "data": {
"type": "security-settings",
"attributes": { "require_mfa": True }
} }
headers = {
"X-Session-Token": "<api-key>",
"Content-Type": "application/vnd.api+json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {'X-Session-Token': '<api-key>', 'Content-Type': 'application/vnd.api+json'},
body: JSON.stringify({data: {type: 'security-settings', attributes: {require_mfa: true}}})
};
fetch('https://api.ctrl-hub.com/v3/security-settings/{security_settings_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.ctrl-hub.com/v3/security-settings/{security_settings_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([
'data' => [
'type' => 'security-settings',
'attributes' => [
'require_mfa' => true
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/vnd.api+json",
"X-Session-Token: <api-key>"
],
]);
$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.ctrl-hub.com/v3/security-settings/{security_settings_id}"
payload := strings.NewReader("{\n \"data\": {\n \"type\": \"security-settings\",\n \"attributes\": {\n \"require_mfa\": true\n }\n }\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("X-Session-Token", "<api-key>")
req.Header.Add("Content-Type", "application/vnd.api+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.ctrl-hub.com/v3/security-settings/{security_settings_id}")
.header("X-Session-Token", "<api-key>")
.header("Content-Type", "application/vnd.api+json")
.body("{\n \"data\": {\n \"type\": \"security-settings\",\n \"attributes\": {\n \"require_mfa\": true\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ctrl-hub.com/v3/security-settings/{security_settings_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["X-Session-Token"] = '<api-key>'
request["Content-Type"] = 'application/vnd.api+json'
request.body = "{\n \"data\": {\n \"type\": \"security-settings\",\n \"attributes\": {\n \"require_mfa\": true\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"type": "security-settings",
"attributes": {
"require_mfa": true
},
"relationships": {
"organisation": {
"data": {
"type": "organisations",
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}
}
},
"jsonapi": {
"version": "1.0"
}
}{
"id": "98ca4a78-b66f-4234-9719-aaf832ee6669",
"status": "400",
"title": "A validation error was encountered",
"source": {
"parameter": "include"
},
"meta": {
"resource": "wrong_value"
}
}{
"id": "05fc9c8d-73b9-4697-9337-57f7a567a48f",
"status": "401",
"title": "You are not authorised to access this resource",
"detail": "In order to access this resource, you need the 'admin' role.",
"code": "AUTH.001"
}{
"errors": [
{
"id": "1b3f2c30-2d56-4d3a-9c44-9be9c2cbf2f0",
"status": "403",
"title": "Forbidden",
"detail": "You do not hold the grant required for this action.",
"code": "AUTH.002"
}
]
}{
"id": "7b4c8f12-3e9a-4d5b-8c6f-1a2b3c4d5e6f",
"status": "404",
"title": "Resource not found",
"detail": "The requested resource could not be found or does not exist.",
"code": "NOT_FOUND.001"
}{
"id": "fe9d9a69-f0a7-4fdc-bb2c-176027f316c5",
"status": "500",
"title": "Internal Server Error",
"detail": "An unexpected error occurred on the server."
}Authorizations
Session token for authentication.
Path Parameters
The security settings to update. Each organisation has one set of security settings, identified by the organisation's id.
Body
The security-settings for the organisation to update.
Show child attributes
Show child attributes