# Understanding Service Account Credentials and the hp-proof-owned-by Field

## Overview

When interacting with the Hyperproof API, proof objects must always be owned by a real human user in the organization. This article explains the `hp-proof-owned-by` field, why it exists, and when you must use it — particularly when authenticating with service account credentials.

## Personal API Credentials vs. Service Account Credentials

Hyperproof supports two types of API clients, each with distinct security and ownership implications:

### Personal API Client

* Inherits your roles and permissions in the organization.
* Objects created or updated via the API are attributed to you (the human user).
* The `hp-proof-owned-by` field is optional — if omitted, you are automatically set as the proof owner.
* The client is private to you; no other user or admin can see it.


### Service Account API Client

* Operates as a distinct, non-human service identity with an assigned organization role.
* Visible to all administrators in the organization.
* Service accounts cannot be owners or assignees on Hyperproof objects.
* The `hp-proof-owned-by` field is required when uploading proof — omitting it results in a 400 Bad Request with the message: "Service accounts cannot be proof owners."


## Why Does This Restriction Exist?

For accountability and traceability, Hyperproof enforces that every object (proof, policy, etc.) is owned by a real user. This has several downstream consequences:

1. **Facepiles and UI attribution** — The Hyperproof UI displays owner avatars (facepiles) on proof items, controls, and tasks. These must resolve to a real user. When a service account uploads proof with `hp-proof-owned-by` set, the UI shows the designated user as the owner and the service account name in the "Uploaded By" column.
2. **Audit trail integrity** — The `createdBy` field records who performed the action (the service account), while `ownedBy` records who is responsible for the proof. This separation preserves a clear chain of custody.
3. **Object lifecycle** — Owners can be notified, assigned follow-up tasks, and are visible in compliance reporting. A non-human identity cannot fulfill these responsibilities.


This same restriction applies to other object types — e.g., service accounts cannot be policy owners either.

## The hp-proof-owned-by Field

| Attribute | Detail |
|  --- | --- |
| Field name | `hp-proof-owned-by` |
| Passed as | Multipart form-data field |
| Value | UUID of an active Hyperproof user |
| Required when | Authenticating with a service account token |
| Optional when | Authenticating with a personal API client token |


The target user must be an active user in the organization — inactive or deprovisioned users cannot be assigned as proof owners.

## Retrieving User UUIDs

Use the Get Organization Users endpoint to retrieve a list of users and their UUIDs:


```bash
curl --silent \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  "https://api.hyperproof.app/v1/users"
```

## Example: Uploading Proof with a Service Account


```bash
# 1. Obtain a token using client credentials flow
ACCESS_TOKEN=$(curl -s -d \
  "grant_type=client_credentials&client_id=$CLIENT_ID&client_secret=$CLIENT_SECRET" \
  https://accounts.hyperproof.app/oauth/token | jq -r '.access_token')

# 2. Upload proof with explicit owner (REQUIRED for service accounts)
curl --request POST \
  --url https://api.hyperproof.app/v1/proof \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --form proof=@"./evidence/SOC2_Report.pdf" \
  --form hp-proof-owned-by="$USER_UUID"
```

## Example: Uploading Proof Linked to a Control


```bash
curl --request POST \
  --url "https://api.hyperproof.app/v1/controls/$CONTROL_ID/proof" \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --form proof=@"./evidence/PrivacyPolicy.pdf" \
  --form hp-proof-owned-by="$USER_UUID"
```

## Security Comparison Summary

| Concern | Personal API Client | Service Account API Client |
|  --- | --- | --- |
| Visibility | Private to the creator | Visible to all org admins |
| Permissions | Inherits your user roles | Has its own assigned role |
| Proof ownership | Automatic (you) | Must specify via `hp-proof-owned-by` |
| `createdBy` attribution | Your user ID | Service account ID |
| UI facepile / owner display | Your avatar | Designated user's avatar |
| Blast radius if compromised | Limited to your permissions | Potentially broader; shared credential |


## Common Errors

| Error | Cause | Fix |
|  --- | --- | --- |
| "Service accounts cannot be proof owners." (400) | `hp-proof-owned-by` omitted or set to the service account's own ID | Provide a valid human user UUID |
| 400 on owner validation | User UUID is inactive or invalid | Use the Users API to retrieve an active user's UUID |