This guide helps you diagnose cases where a GET request succeeds with 200 OK but the response body is an empty array ([]) when retrieving objects (e.g., vendors, controls, risks, tasks) via the Hyperproof API.
- Integrators using service accounts.
- Developers calling object collection endpoints such as
GET /v1/vendors,GET /v1/controls,GET /v1/risks, etc.
Example response (200 + empty body):
{
"get_hyperproof_objects": {
"body": [],
"status": 200
}
}A 200 indicates the request was valid and authorized, but no objects were returned. The most common reason is insufficient role or object‑level permissions for the principal (often a service account), even if the OAuth scope appears correct.
Even with a valid service account and an OAuth client including the correct read scope (e.g., vendor.read, control.read, risk.read), the API may return an empty array if:
- The principal lacks a suitable role (e.g., not an API Admin) and
- The principal does not appear on the object register’s explicit access list (often called the facepile) for that object type.
In Hyperproof, some object types (e.g., vendors) require explicit access in addition to scopes. This behavior is intentional and protects object-level data.
Check whether the service account has a role that confers the needed visibility (e.g., API Admin).
If not, either:
- Assign the API Admin role to the service account, or
- Add the service account to the object register access list (facepile) for the relevant object type(s) in the UI.
Example (assign role via API):
POST /api/organizations/:orgId/users/roles
Content-Type: application/json
{
"roleId": "<API_ADMIN_ROLE_ID>",
"principalId": "<SERVICE_ACCOUNT_ID>",
"principalType": "User"
}Use least privilege when possible: prefer targeted access list membership if full admin is not required.
Ensure the OAuth client includes the read scope for the target object type:
- Vendors →
vendor.read - Controls →
control.read - Risks →
risk.read - (and so on for other objects)
- Vendors →
Quick scope check (example vendors):
curl --request GET \
--url "https://api.hyperproof.app/v1/vendors" \
--header "Authorization: Bearer $ACCESS_TOKEN"If the token lacks the necessary scope, the response may be empty or otherwise constrained.
- After changing roles or access lists, mint a new access token and retry the request.
- Permission changes do not retroactively affect existing tokens.
# Mint a fresh token (method depends on your OAuth flow)
# Then retry
curl --request GET \
--url "https://api.hyperproof.app/v1/vendors" \
--header "Authorization: Bearer $NEW_ACCESS_TOKEN"- Confirm that objects actually exist under the organization in question.
- Review any query parameters (filters, pagination) that could narrow the result set to zero.
Examples:
# No filters: list all vendors visible to the principal
curl -sS -H "Authorization: Bearer $ACCESS_TOKEN" \
"https://api.hyperproof.app/v1/vendors"
# Controls example with a filter that might be too restrictive
curl -sS -H "Authorization: Bearer $ACCESS_TOKEN" \
"https://api.hyperproof.app/v1/controls?status=archived"
# Try removing or adjusting filters if you get []- Double‑check you are calling the intended tenant/org and environment (e.g., production vs. staging). A valid token for a different org with no data will yield
[].
- For object types that enforce explicit access (e.g., vendors), add the service account to the register’s access list in the UI if you choose not to grant a broad admin role.
- After updating access, re‑authenticate (Step 3).
- Token minted after the latest permission changes
- OAuth client includes the correct read scope for the object type
- Service account has a suitable role or appears on the object access list (facepile)
- You are querying the correct org/environment
- Request does not include overly restrictive filters
- There are objects to return
Once the principal has:
- Appropriate role or explicit object access, and
- The necessary read scope(s),
collection endpoints will return the visible objects instead of an empty array.
Examples:
# Vendors
curl -sS -H "Authorization: Bearer $ACCESS_TOKEN" \
"https://api.hyperproof.app/v1/vendors"
# Controls
curl -sS -H "Authorization: Bearer $ACCESS_TOKEN" \
"https://api.hyperproof.app/v1/controls"
# Risks
curl -sS -H "Authorization: Bearer $ACCESS_TOKEN" \
"https://api.hyperproof.app/v1/risks"- Scopes control what a token is allowed to do; roles and access lists control what a principal is allowed to see. You typically need both.
- Prefer least privilege: grant narrow, explicit access where possible.
- Some endpoints (e.g., metadata or helpers) may behave differently; consult the official developer portal for details on each object API.