Table API integration fails to read data from sc_req_item table due to insufficient user permissionsIssue <!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } A dedicated service account requires read-only access to the 'sc_req_item' table via OAuth API integration without admin privileges. The integration uses the PySNC library to invoke API calls to the ServiceNow instance. The PySNC Python library is available from here.Initially, the 'admin' role allowed successful access, but removing it and assigning 'itil' and 'snc_internal' roles caused API call failures. Symptoms<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } - A REST or scripted API call (for example, using the Python `PySNC` library) to `/api/now/table/sc_req_item` returns an empty result set or far fewer records than the account previously retrieved with the admin role. - The same query, executed by the same service account, succeeds when the account has the `admin` role and fails after `admin` is removed. - The account still holds the `itil` and `snc_internal` roles. - No `403 Forbidden` or explicit denial error is returned — the response is HTTP `200 OK` with an empty or filtered `result` array. - Reading individual `sc_req_item` records by `sys_id` may also return no record, even though the record exists. Facts<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } - Issue applies to OAuth (Client ID / Client Secret) integrations where the service account authenticates against the ServiceNow Representational State Transfer (REST) Table API. - The integration target table is `sc_req_item` (Requested Item / RITM). - Reproduced with the open-source `PySNC` Python client (`github.com/ServiceNow/PySNC`); the same behavior applies to any REST client (Postman, cURL, custom code) because access is enforced server-side by Access Control Lists (ACLs). - The service account holds the `itil` and `snc_internal` roles only — admin has been removed. - The behavior is governed by read ACLs on the `sc_req_item` table; at least one read ACL on the table includes a condition requiring both the `snc_internal` role and membership in one of a specific set of groups. Release<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } All releases Cause<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } This behavior is by design. Read access to `sc_req_item` is controlled by Access Control Lists (ACLs) on the table. Beyond holding the `itil` and `snc_internal` roles, at least one read ACL on `sc_req_item` evaluates a condition that requires the requesting user to be a member of one of a specific set of groups (for example, groups owning the request fulfillment, infrastructure, or HR workstreams). When the account had the `admin` role, ACL evaluation was bypassed (admin sees all records), so the integration appeared to work. After the `admin` role was removed, ACL evaluation is enforced normally and the group-membership condition is no longer satisfied, so the records are filtered out at query time. The response contains only the records the account is allowed to see — which can be zero. Resolution<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } Identify the read ACL on `sc_req_item` that includes a group-membership condition, then add the integration service account to one of the groups required by that ACL. Validate the resulting permissions with the Access Analyzer before re-running the integration. 1. Navigate to **System Security > Access Control (ACL)**.2. In the list filter, set **Type** to `record`, **Operation** to `read`, and **Name** to `sc_req_item`. select **Run**.3. Open each read ACL on `sc_req_item` and review the **Requires role** list and the **Condition** and **Script** fields. Look for any ACL that, in addition to requiring `snc_internal`, references group membership — for example, a condition or script that checks whether the current user belongs to a specific group such as a service-desk, infrastructure, or HR-owned group. 4. Note the group names that the ACL requires.5. Navigate to **User Administration > Users** and open the integration service account.6. In the **Groups** related list, select **Edit** and add the account to one of the groups identified in step 4 and select **Save**.7. Confirm that the account retains the `itil` and `snc_internal` roles. Do not grant the `admin` role.8. Validate the resulting permissions using the Access Analyzer: - Navigate to **System Security > Access Analyzer > Analyze Permissions**. - Set **User** to the integration service account. - Set **Table** to `sc_req_item`. - Set **Operation** to `read`. - Select **Analyze**. The report should show that the account has read access to records on `sc_req_item`. 9. Re-run the OAuth API call (or the `PySNC` script) against `sc_req_item`. The expected records are now returned. If the integration also needs to download attachments from a Requested Item, confirm read access to the `sys_attachment` table using the same Access Analyzer procedure. Related Links<!-- /*NS Branding Styles*/ --> .ns-kb-css-body-editor-container { p { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } span { font-size: 12pt; font-family: Lato; color: var(--now-color--text-primary, #000000); } h2 { font-size: 24pt; font-family: Lato; color: var(--now-color--text-primary, black); } h3 { font-size: 18pt; font-family: Lato; color: var(--now-color--text-primary, black); } h4 { font-size: 14pt; font-family: Lato; color: var(--now-color--text-primary, black); } a { font-size: 12pt; font-family: Lato; color: var(--now-color--link-primary, #00718F); } a:hover { font-size: 12pt; color: var(--now-color--link-primary, #024F69); } a:target { font-size: 12pt; color: var(--now-color--link-primary, #032D42); } a:visited { font-size: 12pt; color: var(--now-color--link-primary, #00718f); } ul { font-size: 12pt; font-family: Lato; } li { font-size: 12pt; font-family: Lato; } img { display: ; max-width: ; width: ; height: ; } } - [REST Table API] — official documentation for the Table API used by OAuth integrations. - [Access Control List rules] — how ACLs are evaluated against the requesting user, role, and conditions. - [Access Analyzer] — diagnose effective permissions for a user against a table. - [OAuth 2.0 Inbound] — configuring OAuth client credentials for inbound integrations. - [PySNC Python client]— open-source ServiceNow REST client referenced in the originating case.