Skip to main content
This is not an official U.S. federal government website. The Federal Modernization Workbook is independent technical analysis. It does not represent the position of, and has not been reviewed or endorsed by, any federal agency.

Federal Modernization Workbook

Chapter 03 — The SailPoint Client and Its Scopes

The SailPoint half of the kit’s shared client: ISC tokens by client credentials or a personal access token, Search with searchAfter paging, the Accounts API with limit and offset, and the Microsoft Graph reads the re-read and drift clients make. Declare the ISC and Graph calls with their least-privileged scope or permission, compare an API client’s granted scopes with what each task needs, and keep the workflow-creation scope off the clients that read; with labs against fixtures and a SailPoint sandbox tenant.

An identity governance API client that can read every identity is already a sensitive account. One that can also change them is a second administrator nobody named.

NoteIn this chapter

How the kit’s clients authenticate to SailPoint Identity Security Cloud (ISC) and read identities and accounts, how they read Microsoft Graph, and the scopes each task needs. You add the ISC and Graph rows to Chapter 02’s call list and use kit_calls.py --granted to compare an API client’s scopes, or an app registration’s Graph permissions, with that list. The workflow-creation scope gets its own client, because none of the kit’s clients needs it. Lab 1 runs on a laptop; Lab 2 creates the API clients in a SailPoint sandbox tenant.

TipNarrated tour
Building Ticket-to-Machine, Chapter 03 — The SailPoint Client and Its Scopes: narrated tour · 10 minutes · captions from the player's CC button · Download MP4 · All videos
Jump to a slide (16)

Deck · Narrated deck (about 10 minutes, captions) · Script · Captions. Recorded on November 1, 2026 from the approved chapter.

Goal and audience

Goal. By the end of this chapter you can say which ISC scope and which Graph permission each kit component needs, what a client-credentials token can’t do in ISC, and prove from a test and a comparison that the drift and re-read clients hold read scopes only.

Audience. Developers and identity engineers who own the SailPoint side, and the ISSO who approves API clients. You should read Python. You don’t need a tenant until Lab 2.

The code: examples/servicenow-sailpoint

What exists

clients/python/kit_common.py:

  • The base URL. https://{tenant}.api.identitynow.com, or SAILPOINT_API_BASE for any other domain. A tenant with a vanity URL finds its API details at https://{tenant}.api.identitynow.com/oauth/info.1
  • The token. isc_headers uses a token from a vault if one is set; otherwise the client-credentials grant at /oauth/token. A personal access token’s client ID and secret work the same way.2
  • Search. isc_search_all posts to /v3/search sorted on id and pages with searchAfter, the way SailPoint documents for paging past 10,000 results.3
  • Lists. isc_list_all pages /v3/accounts with limit and offset, 250 at a time, which is the API’s default and maximum.4
  • Graph. graph_headers gets a token by client credentials with a certificate assertion (a secret only as a fallback) from the cloud’s own authority, and graph_get_all follows @odata.nextLink. GRAPH_CLOUD is Global for worldwide and GCC.5

What each client reads is in the implementation example: the drift client reads ISC identities (accounts nested on each) and uncorrelated accounts, and Graph users and, optionally, the directory audit; the re-read client reads one account (GET /v3/accounts/{id}), one identity (Search, id:"...") or one Graph user. ISC Search has no accounts index, which is why a single account is re-read through the Accounts API.6

What this chapter adds

The ISC and Graph rows of config/calls.json:

Call Tasks Least privilege Source
POST /oauth/token (ISC) drift, reread An API client, or a personal access token for a least-privileged user 7
POST /v3/search drift, reread sp:search:read 8
GET /v3/accounts drift idn:accounts:read 9
GET /v3/accounts/{id} reread idn:accounts:read 10
POST /v2025/workflows workflows sp:workflow:manage 11
GET /v1.0/users (Graph) drift User.Read.All (application) 12
GET /v1.0/users/{id} (Graph) reread User.Read.All (application) 13
GET /v1.0/auditLogs/directoryAudits (Graph) drift, optional AuditLog.Read.All (application) 14

The Accounts endpoints accept idn:accounts:read or idn:accounts:manage; the call list names the read scope, and the comparison flags manage as extra. Creating workflows needs sp:workflow:manage; no client in the kit creates them, so that scope belongs to a separate client used once, by hand or by a reviewed pipeline, and then removed (design guidance).

kit_calls.py --system isc --granted "..." compares the scopes an API client was given with what a task needs; --system graph does the same for an app registration’s application permissions. --required-only leaves out optional calls, so an app registration without AuditLog.Read.All still passes for a drift run that doesn’t read the audit.

The tests

Chapter 02’s test_kit_calls.py covers the ISC and Graph calls too: the drift client and the re-read client run against a fake session, and every request they make must match an ISC or Graph row for their task. It also asserts that no task asks ISC or Graph for a scope ending in :manage or ReadWrite.All, except workflow creation. The kit’s original ISC tests in test_kit_common.py (token by client credentials, token from a vault, Search paging, list paging) pass unchanged.

ImportantIllustrative code

The commands below run against a fake session. They show what the code asks for, not that an ISC tenant answers a client-credentials token with data rather than 403. Run Lab 2 in a sandbox tenant first.

Lab 1: fixtures, no tenant

Work in examples/servicenow-sailpoint, with Python 3.10 or later, pytest and requests.

NoteEvery command in Lab 1

Every command in this lab, in order, from examples/servicenow-sailpoint. Each step below says what it does and what to look for.

# Step 1: Run the ISC client tests
python -m pytest tests/python/test_kit_common.py -q -k isc

# Step 2: List what the drift client needs from ISC
python clients/python/kit_calls.py --task drift --system isc

# Step 3: Catch a manage scope on a read client
python clients/python/kit_calls.py --task drift --system isc --granted "sp:search:read,idn:accounts:read,idn:accounts:manage"

# Step 4: Keep the workflow scope on its own client
python clients/python/kit_calls.py --task workflows --system isc --granted "sp:search:read,idn:accounts:read"

# Step 5: Check the Graph app registration
python clients/python/kit_calls.py --task drift --system graph --granted "User.Read.All"
python clients/python/kit_calls.py --task drift --system graph --required-only --granted "User.Read.All"
  1. Run the ISC client tests:

    python -m pytest tests/python/test_kit_common.py -q -k isc

    Terminal window showing python -m pytest tests/python/test_kit_common.py -q -k isc and what it printed

    What the terminal shows, run on the kit’s fixtures (the same output as text)

    4 passed, 15 deselected.

  2. List what the drift client needs from ISC:

    python clients/python/kit_calls.py --task drift --system isc
    Task drift: identity_drift.py: read Graph users, the Entra audit, ISC identities and uncorrelated accounts
    
    isc
      POST   /oauth/token                                               API client (client credentials) or a personal access token
      POST   /v3/search                                                 sp:search:read
      GET    /v3/accounts                                               idn:accounts:read
      needs: idn:accounts:read, sp:search:read

    Terminal window showing python clients/python/kit_calls.py --task drift --system isc and what it printed

    What the terminal shows, run on the kit’s fixtures (the same output as text)
  3. Catch a manage scope on a read client:

    python clients/python/kit_calls.py --task drift --system isc --granted "sp:search:read,idn:accounts:read,idn:accounts:manage"

    Terminal window showing python clients/python/kit_calls.py --task drift --system isc --granted 'sp:se… and what it printed

    What the terminal shows, run on the kit’s fixtures (the same output as text)

    missing: none, extra: idn:accounts:manage, Least privilege does not hold: fix the grant., exit 1.

  4. Keep the workflow scope on its own client. Check the drift client’s scopes against the workflow task:

    python clients/python/kit_calls.py --task workflows --system isc --granted "sp:search:read,idn:accounts:read"

    Terminal window showing python clients/python/kit_calls.py --task workflows --system isc --granted 's… and what it printed

    What the terminal shows, run on the kit’s fixtures (the same output as text)

    missing: sp:workflow:manage, extra: idn:accounts:read, sp:search:read, exit 1: the two jobs need two clients.

  5. Check the Graph app registration, first for a drift run that reads the audit, then for one that doesn’t:

    python clients/python/kit_calls.py --task drift --system graph --granted "User.Read.All"
    python clients/python/kit_calls.py --task drift --system graph --required-only --granted "User.Read.All"

    Terminal window showing python clients/python/kit_calls.py --task drift --system graph --granted 'Use… and what it printed

    What the terminal shows, run on the kit’s fixtures (the same output as text)

    The first reports missing: AuditLog.Read.All and exits 1; the second reports Least privilege holds. and exits 0.

Lab 2: a SailPoint sandbox tenant

Not run by the authors. Use a SailPoint sandbox tenant, never production. How an agency gets one is between it and SailPoint; the public documentation doesn’t say (research gaps, row 21). Work in examples/servicenow-sailpoint. You’ll replace: <tenant> (your sandbox tenant’s name), <reader-scopes> and <workflow-scopes> (the scopes each API client shows, comma-separated), <reader-client-id> and <reader-client-secret> (the reader API client), <pat-client-id> and <pat-client-secret> (a personal access token, only if step 3 needs one) and <employee-id-attribute> (what step 4 finds).

NoteEvery command in Lab 2

Every command in this lab, in order, from examples/servicenow-sailpoint. Each step below says what it does and what to look for.

# Step 1: Find the API base
curl -s "https://<tenant>.api.identitynow.com/oauth/info"

# Step 1: Find the API base
export SAILPOINT_API_BASE="https://<tenant>.api.identitynow.com"

# Step 2: Create two API clients
python clients/python/kit_calls.py --task drift --system isc --granted "<reader-scopes>"
python clients/python/kit_calls.py --task workflows --system isc --granted "<workflow-scopes>"

# Step 3: Try the reader
export SAILPOINT_ACCESS_TOKEN=$(curl -s -X POST "$SAILPOINT_API_BASE/oauth/token" -d grant_type=client_credentials -d client_id="<reader-client-id>" -d client_secret="<reader-client-secret>" | python -c "import json,sys; print(json.load(sys.stdin)['access_token'])")
python clients/python/identity_drift.py --hr-csv tests/fixtures/hr_extract.csv --skip-graph --out-json out/sandbox.json --out-csv out/sandbox.csv

# Step 3: Try the reader
export SAILPOINT_ACCESS_TOKEN=$(curl -s -X POST "$SAILPOINT_API_BASE/oauth/token" -d grant_type=client_credentials -d client_id="<pat-client-id>" -d client_secret="<pat-client-secret>" | python -c "import json,sys; print(json.load(sys.stdin)['access_token'])")
python clients/python/identity_drift.py --hr-csv tests/fixtures/hr_extract.csv --skip-graph --out-json out/sandbox.json --out-csv out/sandbox.csv

# Step 4: Check the employee ID attribute
curl -s -X POST "$SAILPOINT_API_BASE/v3/search?limit=1" -H "Authorization: Bearer $SAILPOINT_ACCESS_TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" --data '{"indices": ["identities"], "query": {"query": "*"}}'

# Step 4: Check the employee ID attribute
export ISC_EMPLOYEE_ID_ATTRIBUTE="<employee-id-attribute>"

# Step 5: Back it out
rm -rf out
unset SAILPOINT_ACCESS_TOKEN
  1. Find the API base. Read your tenant’s OAuth information:

    curl -s "https://<tenant>.api.identitynow.com/oauth/info"

    Set SAILPOINT_API_BASE to the API base. If you use a vanity domain, or the response names a different base, put that base in place of the default one below.15

    export SAILPOINT_API_BASE="https://<tenant>.api.identitynow.com"
  2. Create two API clients. A reader with sp:search:read and idn:accounts:read, for the drift and re-read clients; a workflow client with sp:workflow:manage, used only to create the three workflows. Compare each with the call list:

    python clients/python/kit_calls.py --task drift --system isc --granted "<reader-scopes>"
    python clients/python/kit_calls.py --task workflows --system isc --granted "<workflow-scopes>"
  3. Try the reader. Put its token in SAILPOINT_ACCESS_TOKEN and run the drift client against the sandbox, skipping Graph. The fixture HR extract is enough here: the step tests the reader’s access, not the findings.

    export SAILPOINT_ACCESS_TOKEN=$(curl -s -X POST "$SAILPOINT_API_BASE/oauth/token" -d grant_type=client_credentials -d client_id="<reader-client-id>" -d client_secret="<reader-client-secret>" | python -c "import json,sys; print(json.load(sys.stdin)['access_token'])")
    python clients/python/identity_drift.py --hr-csv tests/fixtures/hr_extract.csv --skip-graph --out-json out/sandbox.json --out-csv out/sandbox.csv

    SailPoint warns that client-credentials tokens have no user context and that calling most admin APIs with one often returns 403.16 If Search or Accounts returns 403, use a personal access token for a dedicated user at the lowest user level those endpoints list (for Accounts: ORG_ADMIN, SOURCE_ADMIN, SOURCE_SUBADMIN or HELPDESK), and record which one worked.1718 With the personal access token:

    export SAILPOINT_ACCESS_TOKEN=$(curl -s -X POST "$SAILPOINT_API_BASE/oauth/token" -d grant_type=client_credentials -d client_id="<pat-client-id>" -d client_secret="<pat-client-secret>" | python -c "import json,sys; print(json.load(sys.stdin)['access_token'])")
    python clients/python/identity_drift.py --hr-csv tests/fixtures/hr_extract.csv --skip-graph --out-json out/sandbox.json --out-csv out/sandbox.csv
  4. Check the employee ID attribute. Search one identity:

    curl -s -X POST "$SAILPOINT_API_BASE/v3/search?limit=1" -H "Authorization: Bearer $SAILPOINT_ACCESS_TOKEN" -H "Content-Type: application/json" -H "Accept: application/json" --data '{"indices": ["identities"], "query": {"query": "*"}}'

    Find where your HR key lives (employeeNumber or attributes.employeeId), and set ISC_EMPLOYEE_ID_ATTRIBUTE to match:

    export ISC_EMPLOYEE_ID_ATTRIBUTE="<employee-id-attribute>"
  5. Back it out. Delete both API clients (or the personal access tokens and the dedicated user), and delete anything the drift run wrote under out:

    rm -rf out
    unset SAILPOINT_ACCESS_TOKEN

The verified facts

Item Value Source
ISC token POST https://{tenant}.api.identitynow.com/oauth/token; client credentials, authorization code and refresh token grants; personal access tokens, up to 10 per user 19
Client-credentials limits No user context (user_id and identity_id unset); most admin APIs often return 403 with such a token 20
Access token A JWT; the example payload carries a scope claim 21
Search POST /v3/search, sp:search:read; searchAfter to page past 10,000 records; user levels ORG_ADMIN, CERT_ADMIN, REPORT_ADMIN, SOURCE_ADMIN, SOURCE_SUBADMIN, ROLE_ADMIN, ROLE_SUBADMIN 22
Search indices accessprofiles, accountactivities, entitlements, events, identities, roles, workflowsummaries; no accounts index 23
List accounts GET /v3/accounts, idn:accounts:read or idn:accounts:manage; uncorrelated filter with eq; limit default and maximum 250 24 25
Get an account GET /v3/accounts/{id}, idn:accounts:read or idn:accounts:manage; user levels ORG_ADMIN, SOURCE_ADMIN, SOURCE_SUBADMIN, HELPDESK 26
Workflows Create needs sp:workflow:manage; list accepts sp:workflow:read or sp:workflow:manage; both name user level ORG_ADMIN 27
Graph: list users, get a user User.Read.All (application), the least privileged for both; Get a user is available in US Government L4 and L5 28 29
Graph: list directory audits AuditLog.Read.All (application), least privileged; available in US Government L4 and L5 30
Graph: list manager Application permissions not supported on GET /users/{id}/manager; GET /users?$expand=manager documented as a way to get the chain 31
GCC endpoints Microsoft 365 GCC uses https://graph.microsoft.com; GCC High graph.microsoft.us; DoD dod-graph.microsoft.us 32
SailPoint Identity Security Cloud FedRAMP Certified, Moderate, agency path, authorized June 5, 2024 33

What couldn’t be verified

  • The API domain of an ISC FedRAMP tenant. The authentication page documents only {tenant}.api.identitynow.com and vanity domains. Kit README verify list, item 6; research gaps, row 22.
  • Whether a client-credentials token gets data from Search and Accounts. SailPoint says most admin APIs often return 403; it doesn’t list which. Verify list, item 8.
  • Whether $expand=manager works under an application permission. Learn’s “List manager” page says application permissions aren’t supported for that endpoint and shows $expand=manager on the users list. Verify list, item 14.
  • Feature parity in the ISC FedRAMP environment for Search, Workflows and the Accounts API. Ask SailPoint; verify list, item 19.

Federal requirements and evidence

What the output proves Requirement it supports KSI Who keeps it
The drift and re-read clients hold read scopes only, and the workflow client holds one scope, removed after use NIST SP 800-53 AC-6 (least privilege) and AC-2 (account management) at Moderate34 KSI-IAM-ELP; KSI-IAM-SNU The kit_calls.py --granted output with the API client’s approval
The Graph app registration holds User.Read.All and, only if the audit is read, AuditLog.Read.All, with a certificate AC-6; IA-5 (authenticator management) for the certificate KSI-IAM-ELP; KSI-IAM-APM The app registration’s permissions and credential, reviewed with the call list
No component of Pass 1 can write to ISC, Entra ID or Active Directory AC-6; Book 13’s rule that the coordination layer never writes the configuration itself KSI-IAM-ELP The call list and its test
Lab 1, step 1: the ISC client handles tokens, paging and the search cursor as tested SA-11 (developer testing) at Moderate35 KSI-SCR-MIT The pytest tests/python/test_kit_common.py -k isc run, in the pull request’s checks
Lab 1, step 2: the scopes the drift client needs from ISC, each with the vendor page that says so AC-6 KSI-IAM-ELP The kit_calls.py --task drift --system isc output, attached to the API client request
Lab 1, step 3: a manage scope on a read client is named, and the command exits 1 AC-6 KSI-IAM-ELP The kit_calls.py --granted output that lists extra:, kept until the grant is fixed
Lab 1, step 4: the workflow scope needs its own client AC-6; AC-5 (separation of duties) at Moderate36 KSI-IAM-ELP; KSI-IAM-JIT The kit_calls.py --task workflows --granted output
Lab 1, step 5: the Graph app registration needs AuditLog.Read.All only when the drift run reads the audit AC-6 KSI-IAM-ELP The two kit_calls.py --system graph outputs, kept with the app registration’s approval
Lab 2, step 1: the tenant’s API base, the end of the flow from the kit to ISC CA-3 (information exchange) at Moderate37 KSI-SCR-MON The /oauth/info response, kept with the data-flow record
Lab 2, step 2: a reader client and a separate workflow client, each matching the call list AC-2; AC-6; IA-5 for each client secret KSI-IAM-SNU; KSI-IAM-ELP The two kit_calls.py --granted outputs, kept with the API client approvals
Lab 2, step 3: the reader’s scopes are enough for the drift client to read ISC AC-6 KSI-IAM-ELP The terminal output, with any 403 recorded. out/sandbox.json and out/sandbox.csv hold fixture HR data and are deleted in step 5
Lab 2, step 4: the attribute that holds the HR key, so accounts correlate to one person CM-8 (system component inventory) at Moderate, read for identities (inference)38 KSI-PIY-GIV The ISC_EMPLOYEE_ID_ATTRIBUTE value, recorded in the deployment’s configuration
Lab 2, step 5: no test API client, token or output is left AC-2; IA-5 KSI-IAM-SNU The tenant’s API client list; rm -rf out and unset SAILPOINT_ACCESS_TOKEN clear the laptop
Production runs on SailPoint Identity Security Cloud, which the verified facts list as FedRAMP Certified, not on a sandbox FedRAMP authorization of the cloud services used; SA-9 (external system services) at Moderate39 KSI-SCR-MIT; KSI-SCR-MON The ISSO, with the authorization package and the Marketplace listing with its read date

The KSI column names the FedRAMP 20x Key Security Indicators whose related SP 800-53 controls include the row’s control.40 KSIs are indicators for cloud service providers: the agency authorizes its own system and lines its own evidence up with what its providers report against them; it doesn’t report KSIs itself.

Dangers

Danger What happens The guard
A manage scope on a read client A stolen token can change accounts --granted flags idn:accounts:manage as extra
The workflow scope left on a standing client Anyone with that token can add or change workflows that call out of SailPoint A separate client, used once; the call list shows no client needs it
A personal access token for an administrator The kit runs as ORG_ADMIN A dedicated user at the lowest user level that works, recorded in Lab 2
Offset paging past 10,000 search results Results stop silently searchAfter sorted on id; tested
The wrong Graph cloud Tokens and data from the wrong cloud, or none GRAPH_CLOUD has three values and refuses others; GCC is Global
A client secret for Graph A long-lived secret in a pipeline Certificate assertion first; the secret is a fallback

Checklist

Back to top

Footnotes

  1. SailPoint Developer, “Authentication” (token endpoint, grant types, personal access tokens, client-credentials limits, /oauth/info, JWT access tokens), https://developer.sailpoint.com/docs/api/authentication (read November 1, 2026).↩︎

  2. SailPoint Developer, “Authentication” (token endpoint, grant types, personal access tokens, client-credentials limits, /oauth/info, JWT access tokens), https://developer.sailpoint.com/docs/api/authentication (read November 1, 2026).↩︎

  3. SailPoint, Identity Security Cloud OpenAPI specification, v3, searchPost (sp:search:read, user levels, searchAfter), https://github.com/sailpoint-oss/api-specs/blob/main/idn/v3/paths/search-post.yaml (read November 1, 2026, at commit 7f6741e).↩︎

  4. SailPoint, Identity Security Cloud OpenAPI specification, v3, limit parameter (default 250, maximum 250), https://github.com/sailpoint-oss/api-specs/blob/main/idn/v3/parameters/limit.yaml (read November 1, 2026).↩︎

  5. Microsoft Learn, “Microsoft Graph national cloud deployments,” service root endpoints, https://learn.microsoft.com/graph/deployments (read November 1, 2026).↩︎

  6. SailPoint, Identity Security Cloud OpenAPI specification, v3, search Index enumeration, https://github.com/sailpoint-oss/api-specs/blob/main/idn/v3/schemas/search/Index.yaml (read November 1, 2026).↩︎

  7. SailPoint Developer, “Authentication” (token endpoint, grant types, personal access tokens, client-credentials limits, /oauth/info, JWT access tokens), https://developer.sailpoint.com/docs/api/authentication (read November 1, 2026).↩︎

  8. SailPoint, Identity Security Cloud OpenAPI specification, v3, searchPost (sp:search:read, user levels, searchAfter), https://github.com/sailpoint-oss/api-specs/blob/main/idn/v3/paths/search-post.yaml (read November 1, 2026, at commit 7f6741e).↩︎

  9. SailPoint, Identity Security Cloud OpenAPI specification, v3, listAccounts (scopes, user levels, filters), https://github.com/sailpoint-oss/api-specs/blob/main/idn/v3/paths/accounts.yaml (read November 1, 2026).↩︎

  10. SailPoint, Identity Security Cloud OpenAPI specification, v3, getAccount (scopes, user levels), https://github.com/sailpoint-oss/api-specs/blob/main/idn/v3/paths/account.yaml (read November 1, 2026).↩︎

  11. SailPoint, Identity Security Cloud OpenAPI specification, v2025, createWorkflow and listWorkflows (scopes; user level ORG_ADMIN, added at commit 2a1f293), https://github.com/sailpoint-oss/api-specs/blob/main/idn/v2025/paths/workflows/workflows.yaml (read November 1, 2026; re-read November 9, 2026).↩︎

  12. Microsoft Learn, “List users,” permissions, https://learn.microsoft.com/graph/api/user-list?view=graph-rest-1.0 (read November 1, 2026).↩︎

  13. Microsoft Learn, “Get a user,” national cloud availability and permissions, https://learn.microsoft.com/graph/api/user-get?view=graph-rest-1.0 (read November 1, 2026).↩︎

  14. Microsoft Learn, “List directoryAudits,” national cloud availability and permissions, https://learn.microsoft.com/graph/api/directoryaudit-list?view=graph-rest-1.0 (read November 1, 2026).↩︎

  15. SailPoint Developer, “Authentication” (token endpoint, grant types, personal access tokens, client-credentials limits, /oauth/info, JWT access tokens), https://developer.sailpoint.com/docs/api/authentication (read November 1, 2026).↩︎

  16. SailPoint Developer, “Authentication” (token endpoint, grant types, personal access tokens, client-credentials limits, /oauth/info, JWT access tokens), https://developer.sailpoint.com/docs/api/authentication (read November 1, 2026).↩︎

  17. SailPoint, Identity Security Cloud OpenAPI specification, v3, getAccount (scopes, user levels), https://github.com/sailpoint-oss/api-specs/blob/main/idn/v3/paths/account.yaml (read November 1, 2026).↩︎

  18. SailPoint, Identity Security Cloud OpenAPI specification, v3, searchPost (sp:search:read, user levels, searchAfter), https://github.com/sailpoint-oss/api-specs/blob/main/idn/v3/paths/search-post.yaml (read November 1, 2026, at commit 7f6741e).↩︎

  19. SailPoint Developer, “Authentication” (token endpoint, grant types, personal access tokens, client-credentials limits, /oauth/info, JWT access tokens), https://developer.sailpoint.com/docs/api/authentication (read November 1, 2026).↩︎

  20. SailPoint Developer, “Authentication” (token endpoint, grant types, personal access tokens, client-credentials limits, /oauth/info, JWT access tokens), https://developer.sailpoint.com/docs/api/authentication (read November 1, 2026).↩︎

  21. SailPoint Developer, “Authentication” (token endpoint, grant types, personal access tokens, client-credentials limits, /oauth/info, JWT access tokens), https://developer.sailpoint.com/docs/api/authentication (read November 1, 2026).↩︎

  22. SailPoint, Identity Security Cloud OpenAPI specification, v3, searchPost (sp:search:read, user levels, searchAfter), https://github.com/sailpoint-oss/api-specs/blob/main/idn/v3/paths/search-post.yaml (read November 1, 2026, at commit 7f6741e).↩︎

  23. SailPoint, Identity Security Cloud OpenAPI specification, v3, search Index enumeration, https://github.com/sailpoint-oss/api-specs/blob/main/idn/v3/schemas/search/Index.yaml (read November 1, 2026).↩︎

  24. SailPoint, Identity Security Cloud OpenAPI specification, v3, listAccounts (scopes, user levels, filters), https://github.com/sailpoint-oss/api-specs/blob/main/idn/v3/paths/accounts.yaml (read November 1, 2026).↩︎

  25. SailPoint, Identity Security Cloud OpenAPI specification, v3, limit parameter (default 250, maximum 250), https://github.com/sailpoint-oss/api-specs/blob/main/idn/v3/parameters/limit.yaml (read November 1, 2026).↩︎

  26. SailPoint, Identity Security Cloud OpenAPI specification, v3, getAccount (scopes, user levels), https://github.com/sailpoint-oss/api-specs/blob/main/idn/v3/paths/account.yaml (read November 1, 2026).↩︎

  27. SailPoint, Identity Security Cloud OpenAPI specification, v2025, createWorkflow and listWorkflows (scopes; user level ORG_ADMIN, added at commit 2a1f293), https://github.com/sailpoint-oss/api-specs/blob/main/idn/v2025/paths/workflows/workflows.yaml (read November 1, 2026; re-read November 9, 2026).↩︎

  28. Microsoft Learn, “List users,” permissions, https://learn.microsoft.com/graph/api/user-list?view=graph-rest-1.0 (read November 1, 2026).↩︎

  29. Microsoft Learn, “Get a user,” national cloud availability and permissions, https://learn.microsoft.com/graph/api/user-get?view=graph-rest-1.0 (read November 1, 2026).↩︎

  30. Microsoft Learn, “List directoryAudits,” national cloud availability and permissions, https://learn.microsoft.com/graph/api/directoryaudit-list?view=graph-rest-1.0 (read November 1, 2026).↩︎

  31. Microsoft Learn, “List manager,” permissions and HTTP request, https://learn.microsoft.com/graph/api/user-list-manager?view=graph-rest-1.0 (read November 1, 2026).↩︎

  32. Microsoft Learn, “Microsoft Graph national cloud deployments,” service root endpoints, https://learn.microsoft.com/graph/deployments (read November 1, 2026).↩︎

  33. FedRAMP Marketplace data, https://www.fedramp.gov/marketplace/products.json (last change November 1, 2026): SailPoint Identity Security Cloud, FR2001938710A (read November 1, 2026).↩︎

  34. National Institute of Standards and Technology, SP 800-53B Moderate baseline, release 5.2.0 OSCAL profile (includes AC-2, AC-5, AC-6, CA-3, CM-8, IA-5, SA-9 and SA-11), https://github.com/usnistgov/oscal-content/blob/main/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_MODERATE-baseline_profile.json (read November 1, 2026).↩︎

  35. National Institute of Standards and Technology, SP 800-53B Moderate baseline, release 5.2.0 OSCAL profile (includes AC-2, AC-5, AC-6, CA-3, CM-8, IA-5, SA-9 and SA-11), https://github.com/usnistgov/oscal-content/blob/main/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_MODERATE-baseline_profile.json (read November 1, 2026).↩︎

  36. National Institute of Standards and Technology, SP 800-53B Moderate baseline, release 5.2.0 OSCAL profile (includes AC-2, AC-5, AC-6, CA-3, CM-8, IA-5, SA-9 and SA-11), https://github.com/usnistgov/oscal-content/blob/main/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_MODERATE-baseline_profile.json (read November 1, 2026).↩︎

  37. National Institute of Standards and Technology, SP 800-53B Moderate baseline, release 5.2.0 OSCAL profile (includes AC-2, AC-5, AC-6, CA-3, CM-8, IA-5, SA-9 and SA-11), https://github.com/usnistgov/oscal-content/blob/main/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_MODERATE-baseline_profile.json (read November 1, 2026).↩︎

  38. National Institute of Standards and Technology, SP 800-53B Moderate baseline, release 5.2.0 OSCAL profile (includes AC-2, AC-5, AC-6, CA-3, CM-8, IA-5, SA-9 and SA-11), https://github.com/usnistgov/oscal-content/blob/main/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_MODERATE-baseline_profile.json (read November 1, 2026).↩︎

  39. National Institute of Standards and Technology, SP 800-53B Moderate baseline, release 5.2.0 OSCAL profile (includes AC-2, AC-5, AC-6, CA-3, CM-8, IA-5, SA-9 and SA-11), https://github.com/usnistgov/oscal-content/blob/main/nist.gov/SP800-53/rev5/json/NIST_SP-800-53_rev5_MODERATE-baseline_profile.json (read November 1, 2026).↩︎

  40. FedRAMP, “Key Security Indicators,” FedRAMP Consolidated Rules for 2026, indicator titles and “Related SP 800-53 Controls,” https://www.fedramp.gov/2026/reference/key-security-indicators/ (read November 2, 2026).↩︎