# Troubleshooting Empty Responses

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.

## Who this is for

* Integrators using service accounts.
* Developers calling object collection endpoints such as `GET /v1/vendors`, `GET /v1/controls`, `GET /v1/risks`, etc.


## Common symptom

Example response (200 + empty body):


```json
{
  "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.

## Why this happens

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.


## Step-by-step resolution

### Confirm role assignment

* 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):


```http
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.


### Verify OAuth scope(s)

* 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)


Quick scope check (example vendors):


```bash
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.

### Re‑authenticate after permissions change

* After changing roles or access lists, mint a new access token and retry the request.
* Permission changes do not retroactively affect existing tokens.



```bash
# 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"
```

### Check data existence and filters

* 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:


```bash
# 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 []
```

### Validate organization / environment

* 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 `[]`.


### Object‑level access (facepile)

* 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).


## Quick diagnostic checklist

* [ ] 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


## Expected behavior after resolution

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:


```bash
# 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"
```

## Notes

* 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.