Hey folks. I’m trying to build a quick audit script to list all OAuth clients in our org and verify their scope assignments. We’ve got a hybrid setup and I need to ensure none of the legacy integrations are holding onto overly broad scopes like organization:all.
I’ve been looking at the /api/v2/oauth/clients endpoint. The docs say it returns a list of client objects. Here’s the basic cURL I’m using for testing:
curl -X GET "https://mycompany.mypurecloud.com/api/v2/oauth/clients" \
-H "Authorization: Bearer <access_token>" \
-H "Accept: application/json"
The response comes back with a 200 OK, which is good. The JSON payload looks something like this:
{
"pageSize": 25,
"pageNumber": 1,
"total": 42,
"entities": [
{
"id": "abc-123",
"name": "Legacy CRM Connector",
"clientId": "some-client-id",
"scopes": [
"organization:read",
"conversation:write"
]
}
]
}
My issue is with the pagination and filtering. The total is 42, but pageSize is 25. I have to loop through the pages to get the full list. Is there a query parameter I can pass to get all clients in one go? I tried pageSize=100 but it seems capped at 1000 and still feels clunky for a simple audit.
Also, I noticed some clients in the response don’t have a scopes array populated. They just show "scopes": []. Does that mean they have no scopes assigned, or is it a bug in the API response? If a client has no scopes, can it still authenticate? I’m worried about false positives in my audit script.
Here’s the Python snippet I’m using to fetch the pages:
import requests
def get_all_clients(base_url, token):
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/json"
}
url = f"{base_url}/api/v2/oauth/clients"
all_clients = []
page = 1
while True:
params = {"pageSize": 100, "pageNumber": page}
response = requests.get(url, headers=headers, params=params)
if response.status_code != 200:
print(f"Error: {response.status_code}")
break
data = response.json()
if not data.get("entities"):
break
all_clients.extend(data["entities"])
if len(data["entities"]) < data["pageSize"]:
break
page += 1
return all_clients
Is there a better way to check the actual effective scopes? The scopes field in the client object seems static. If a client is linked to a user or role, do those scopes merge? I can’t find clear docs on how client scopes interact with user/role scopes during the OAuth grant flow.
Any pointers on the best practice for auditing this? I just want a clean list of client ID, name, and all possible scopes they can request.