Disabling or deleting a user
This guide covers the two ways to end a user's access to an organization with the API:
- Disabling — reversibly suspends access. The user record is kept and can be re-enabled at any time.
- Deleting — permanently removes the user and their access.
- A valid set of API credentials
- A valid access token (see: Get a token) with the
stonal.user.writescope - An organization code
Choosing between disabling and deleting
| Disabling | Deleting | |
|---|---|---|
| Reversible? | Yes — re-enable at any time | No — permanent |
| User record | Kept (surfaced as disabled) | Removed |
| Scope | The organization in the request path | The organization in the request path |
| Typical use | Temporary suspension (leave, offboarding in progress, lost device) | Permanent removal |
Step 1: Retrieving the user UID
Both operations need the user's UID. Search for the user to get it.
GET /v2/organizations/DEMO/users?pageNumber=1&pageSize=10&q=john.doe@example.com
If the user exists, you'll receive a 200 response with the user's details including their UID and current disabled state.
Disabling a user
How disabling works
Disabling is scoped to a single organization. The operation sets a flag on the user's access in the organization in the request path; the user immediately loses access to that organization's assets, applications, and reports. Their access in any other organization is untouched.
Because a Stonal identity is a single sign-in account shared across every organization the person belongs to, the underlying account is only disabled — preventing sign-in entirely — once the user has been disabled in all of their organizations. As soon as they are re-enabled in any one organization, sign-in is restored.
A few things to keep in mind:
- Still discoverable — disabled users keep appearing in user listings with
disabled: true, so you can find and re-enable them. - Eventual revocation — permission checks are cached for up to ~1 minute, so access is fully revoked within ~60 seconds (the same behaviour as deletion).
- No self-disable — you cannot disable the account you are authenticated as (returns
409). - v2 only — the disable and enable endpoints are available on the v2 API.
Disable the user
See: API Specification
POST /v2/organizations/DEMO/users/5dbbc53c-1a22-4f6f-883c-74c04fe905f5/disable
- Python
- PHP
- JavaScript
- Java
- Go
- C#
import requests
BASE_URL = "https://api.stonal.io/users"
TOKEN = "<access_token>"
resp = requests.post(
f"{BASE_URL}/v2/organizations/DEMO/users/5dbbc53c-1a22-4f6f-883c-74c04fe905f5/disable",
headers={"Authorization": f"Bearer {TOKEN}"},
)
print(resp.status_code)
<?php
$baseUrl = "https://api.stonal.io/users";
$token = "<access_token>";
$ch = curl_init("$baseUrl/v2/organizations/DEMO/users/5dbbc53c-1a22-4f6f-883c-74c04fe905f5/disable");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => ["Authorization: Bearer $token"],
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE) . PHP_EOL;
curl_close($ch);
const baseUrl = "https://api.stonal.io/users";
const token = "<access_token>";
const res = await fetch(
`${baseUrl}/v2/organizations/DEMO/users/5dbbc53c-1a22-4f6f-883c-74c04fe905f5/disable`,
{
method: "POST",
headers: { Authorization: `Bearer ${token}` },
}
);
console.log(res.status);
import java.net.URI;
import java.net.http.*;
String baseUrl = "https://api.stonal.io/users";
String token = "<access_token>";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/v2/organizations/DEMO/users/5dbbc53c-1a22-4f6f-883c-74c04fe905f5/disable"))
.header("Authorization", "Bearer " + token)
.POST(HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
package main
import (
"fmt"
"net/http"
)
func main() {
baseURL := "https://api.stonal.io/users"
token := "<access_token>"
req, _ := http.NewRequest("POST", baseURL+"/v2/organizations/DEMO/users/5dbbc53c-1a22-4f6f-883c-74c04fe905f5/disable", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.StatusCode)
}
using System.Net.Http;
using System.Net.Http.Headers;
var baseUrl = "https://api.stonal.io/users";
var token = "<access_token>";
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = await client.PostAsync($"{baseUrl}/v2/organizations/DEMO/users/5dbbc53c-1a22-4f6f-883c-74c04fe905f5/disable", null);
Console.WriteLine((int)response.StatusCode);
Path parameters:
organizationCode: Your client code (e.g., "DEMO")uid: UID of the user to disable (e.g., "5dbbc53c-1a22-4f6f-883c-74c04fe905f5")
Possible responses:
- 204: User has been successfully disabled
- 404: User to disable does not exist
- 409: The user cannot be disabled (for example, you cannot disable your own account)
Re-enable the user
To restore access, call the enable endpoint with the same UID. This clears the disabled flag in the organization and, if the user's sign-in account was disabled, restores it so they can authenticate again.
See: API Specification
POST /v2/organizations/DEMO/users/5dbbc53c-1a22-4f6f-883c-74c04fe905f5/enable
- Python
- PHP
- JavaScript
- Java
- Go
- C#
import requests
BASE_URL = "https://api.stonal.io/users"
TOKEN = "<access_token>"
resp = requests.post(
f"{BASE_URL}/v2/organizations/DEMO/users/5dbbc53c-1a22-4f6f-883c-74c04fe905f5/enable",
headers={"Authorization": f"Bearer {TOKEN}"},
)
print(resp.status_code)
<?php
$baseUrl = "https://api.stonal.io/users";
$token = "<access_token>";
$ch = curl_init("$baseUrl/v2/organizations/DEMO/users/5dbbc53c-1a22-4f6f-883c-74c04fe905f5/enable");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => ["Authorization: Bearer $token"],
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE) . PHP_EOL;
curl_close($ch);
const baseUrl = "https://api.stonal.io/users";
const token = "<access_token>";
const res = await fetch(
`${baseUrl}/v2/organizations/DEMO/users/5dbbc53c-1a22-4f6f-883c-74c04fe905f5/enable`,
{
method: "POST",
headers: { Authorization: `Bearer ${token}` },
}
);
console.log(res.status);
import java.net.URI;
import java.net.http.*;
String baseUrl = "https://api.stonal.io/users";
String token = "<access_token>";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/v2/organizations/DEMO/users/5dbbc53c-1a22-4f6f-883c-74c04fe905f5/enable"))
.header("Authorization", "Bearer " + token)
.POST(HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
package main
import (
"fmt"
"net/http"
)
func main() {
baseURL := "https://api.stonal.io/users"
token := "<access_token>"
req, _ := http.NewRequest("POST", baseURL+"/v2/organizations/DEMO/users/5dbbc53c-1a22-4f6f-883c-74c04fe905f5/enable", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.StatusCode)
}
using System.Net.Http;
using System.Net.Http.Headers;
var baseUrl = "https://api.stonal.io/users";
var token = "<access_token>";
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = await client.PostAsync($"{baseUrl}/v2/organizations/DEMO/users/5dbbc53c-1a22-4f6f-883c-74c04fe905f5/enable", null);
Console.WriteLine((int)response.StatusCode);
Path parameters:
organizationCode: Your client code (e.g., "DEMO")uid: UID of the user to re-enable (e.g., "5dbbc53c-1a22-4f6f-883c-74c04fe905f5")
Possible responses:
- 204: User has been successfully enabled
- 404: User to enable does not exist
Deleting a user
Deletion is permanent and cannot be undone. To revoke access in a way you can reverse, disable the user instead.
See: API Specification
DELETE /v2/organizations/DEMO/users/019619df-4768-76b7-81e3-2c56d374df46
- Python
- PHP
- JavaScript
- Java
- Go
- C#
import requests
BASE_URL = "https://api.stonal.io/users"
TOKEN = "<access_token>"
resp = requests.delete(
f"{BASE_URL}/v2/organizations/DEMO/users/019619df-4768-76b7-81e3-2c56d374df46",
headers={"Authorization": f"Bearer {TOKEN}"},
)
print(resp.status_code)
<?php
$baseUrl = "https://api.stonal.io/users";
$token = "<access_token>";
$ch = curl_init("$baseUrl/v2/organizations/DEMO/users/019619df-4768-76b7-81e3-2c56d374df46");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_HTTPHEADER => ["Authorization: Bearer $token"],
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_HTTP_CODE) . PHP_EOL;
curl_close($ch);
const baseUrl = "https://api.stonal.io/users";
const token = "<access_token>";
const res = await fetch(
`${baseUrl}/v2/organizations/DEMO/users/019619df-4768-76b7-81e3-2c56d374df46`,
{
method: "DELETE",
headers: { Authorization: `Bearer ${token}` },
}
);
console.log(res.status);
import java.net.URI;
import java.net.http.*;
String baseUrl = "https://api.stonal.io/users";
String token = "<access_token>";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/v2/organizations/DEMO/users/019619df-4768-76b7-81e3-2c56d374df46"))
.header("Authorization", "Bearer " + token)
.DELETE()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
package main
import (
"fmt"
"net/http"
)
func main() {
baseURL := "https://api.stonal.io/users"
token := "<access_token>"
req, _ := http.NewRequest("DELETE", baseURL+"/v2/organizations/DEMO/users/019619df-4768-76b7-81e3-2c56d374df46", nil)
req.Header.Set("Authorization", "Bearer "+token)
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println(resp.StatusCode)
}
using System.Net.Http;
using System.Net.Http.Headers;
var baseUrl = "https://api.stonal.io/users";
var token = "<access_token>";
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = await client.DeleteAsync($"{baseUrl}/v2/organizations/DEMO/users/019619df-4768-76b7-81e3-2c56d374df46");
Console.WriteLine((int)response.StatusCode);
Path parameters:
organizationCode: Your client code (e.g., "DEMO")uid: UID of the user to delete (e.g., "019619df-4768-76b7-81e3-2c56d374df46")
Possible responses:
- 204: User has been successfully deleted
- 404: User to delete does not exist
- 409: The user cannot be deleted due to a conflict (for example, a referential constraint)
Notes
- All operations are organization-scoped and only affect access within the organization in the request path.
- The user UID must be obtained from a previous search or stored as an external id on your side.
- Disabling and re-enabling are idempotent — disabling an already-disabled user, or enabling an already-enabled user, succeeds and leaves the state unchanged.
- Deletion is permanent and cannot be undone; use disabling when you may need to restore access later.
Error Handling
Stonal APIs return a consistent error envelope: { "type", "title", "detail" }. Validation failures (422) replace detail with a per-field errors array.
| Status | type | Meaning |
|---|---|---|
400 | tag:InvalidBody / tag:InvalidContentType | The request body or content type is invalid |
401 | tag:Unauthenticated | Missing or expired authentication token |
403 | tag:ForbiddenAccess | The token lacks permission for this resource |
422 | tag:ValidationError | One or more fields failed validation (see errors[]) |
500 | tag:InternalError | Unexpected server error |
{
"type": "tag:ValidationError",
"title": "Invalid request",
"errors": [
{ "field": "email", "detail": "Email is required" }
]
}