# Uploading and retrieving proof

This article explains how to upload, list, and download proof files using the Hyperproof API. It provides a plain-language overview of the official API documentation and includes practical, original examples to help you implement each step.

## Authentication

- Include a Bearer access token in the `Authorization` header for every request
- Tokens are obtained via Hyperproof OAuth


**Example header** - `Authorization: Bearer <ACCESS_TOKEN>`

## Uploading a proof file (organization scope)

**Method and URL** - `POST https://api.hyperproof.app/v1/proof`

**Request** (multipart/form-data)

- `proof` (file, required) - The file to upload.
- `hp-proof-owned-by` (string, optional) - The user ID designating the proof owner.


**Behavior**

- Upon success, returns JSON metadata about the uploaded proof, including `id`, `filename`, `version`, `size`, `createdBy/On`, `updatedBy/On`.


**Sample**


```bash
curl --request POST \
  --url https://api.hyperproof.app/v1/proof \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --form proof=@"./policies/AcceptableUse.pdf"
```

**With explicit owner**


```bash
curl --request POST \
  --url https://api.hyperproof.app/v1/proof \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --form proof=@"./policies/AcceptableUse.pdf" \
  --form hp-proof-owned-by="$USER_ID"
```

**Uploading Testable CSV proof**

When sending CSV files, you need to explicitly declare the type as text/csv. This tells Hyperproof to treat the uploaded blob as tabular data. This allows the CSV proof to be usable in automated tests.


```bash
curl --request POST \
  --url https://api.hyperproof.app/v1/proof \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --form proof=@"./policies/AcceptableUse.csv:type=text/csv" \
  --form hp-proof-owned-by="$USER_ID"
  --form contentType="text/csv"
```

**Updating Testable CSV proof**

After uploading a CSV file intended for automated testing, a PATCH request should be made to create the schema to be tested.
The body of the request will define the CSV fields and types for the automated testing feature. Available types include text , number , boolean , and date.


```bash
curl --request PATCH 'https://api.hyperproof.app/v1/proof/:proofid' \
--header 'Content-Type: application/json' \
--header 'Authorization: ••••••' \
--data '{
    "isPrivate": false,
    "schema": {
        "class": "CsvFileSchema",
        "fields": [{
            "name": "Name",
            "type": "text"
        }, {
            "name": "Email",
            "type": "text"
        }]
    }
}'
```

## Uploading a new version of existing proof

**Method and URL** - `POST https://api.hyperproof.app/v1/proof/{proofId}/versions`

**Request** (multipart/form-data)

- `proof` (file, required) - The new file contents.


**Behavior**

- Creates a new version for the referenced proof item.
- The `version` value increases by 1 from the highest existing version.


**Sample**


```bash
curl --request POST \
  --url "https://api.hyperproof.app/v1/proof/$PROOF_ID/versions" \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --form proof=@"./policies/AcceptableUse_v7.pdf"
```

## Uploading and immediately linking proof to an object

You can upload a proof file and directly link it to an object such as a control, label, or task.

**URL pattern** - `POST https://api.hyperproof.app/v1/{objectType}s/{objectId}/proof`

- `objectType` can be `control`, `label`, or `task`.
- Use multi-part/form-data with a `proof` file field.


**Sample (control)**


```bash
CONTROL_ID=12345678-90ab-cdef-1234-567890abcdef
curl --request POST \
  --url "https://api.hyperproof.app/v1/controls/$CONTROL_ID/proof" \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --form proof=@"./evidence/PrivacyPolicy.pdf"
```

## Uploading proof using the API with a Service Account

To successfully upload a proof via the API using a service account, you must explicitly assign the proof's ownership to one of the Hyperproof users. When making your API call to upload the proof, include the following header or metadata field:

- Use multi-part/form-data with a `proof` file field.
- `hp-proof-owned-by` - UUID of the user who should own the proof ([Retrieve a list of users UUIDs.](https://developer.hyperproof.app/hyperproof-api/users/users.openapi/other/get-org-users))


**Sample**


```bash
curl --request POST \
  --url https://api.hyperproof.app/v1/proof \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  --form proof=@"./policies/AcceptableUse.pdf" \
  --form hp-proof-owned-by="$USER_ID"
```

## Listing proof metadata (organization)

**Method and URL** - `GET https://api.hyperproof.app/v1/proof`

**Pagination**

- `limit` (integer, optional) - This is the page size. The default is 25.
- If more items exist than the page size, the response includes an `offsetToken` you can pass as `offset` to fetch the next page.


**Sorting**

- `sortBy` - One of `createdBy`, `createdOn`, `filename`, or `uploadedOn`. The default is `uploadedOn`.
- `sortDirection` - Choose either `asc` (ascending) or `desc` (descending). The default is `desc`.
- `uploadedOn` - Updates when you add a new version; `createdOn` remains fixed.


**Filtering**

- `ownedByMe=true` - Returns proof owned by the currently authorized user.
- `search=<value>` - Filters by filename matches.


**Sample**


```bash
curl --silent \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  "https://api.hyperproof.app/v1/proof?limit=100&sortBy=filename&sortDirection=asc&ownedByMe=true"
```

**Follow-up page using offset token**


```bash
curl --silent \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  "https://api.hyperproof.app/v1/proof?offset=$OFFSET_TOKEN"
```

## Listing proof metadata linked to a specific object

Use the same endpoint with object filters.

**Method and URL** - `GET https://api.hyperproof.app/v1/proof?objectType=<control|label|task>&objectId=<ID>`

br
**Sample (first page for a control)**


```bash
curl --silent \
  --header "Authorization: Bearer $ACCESS_TOKEN" \
  "https://api.hyperproof.app/v1/proof?objectType=control&objectId=$CONTROL_ID&limit=100"
```

## Downloading proof file contents

**Method and URL** - `GET https://api.hyperproof.app/v1/proof/{proofId}/contents`

**Behavior**

- Returns the raw file in the response body.
- The original file name is provided by the `content-disposition` response header.
- To fetch a particular version, add `?version=<n>`.


**Sample (latest version)**


```bash
curl -O --remote-header-name \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  "https://api.hyperproof.app/v1/proof/$PROOF_ID/contents"
```

**Sample (specific version)**


```bash
curl -O --remote-header-name \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  "https://api.hyperproof.app/v1/proof/$PROOF_ID/contents?version=3"
```

## Response fields (common)

While the exact shape can evolve, responses commonly include:

- `id` (UUID)
- `filename`
- `version` (integer)
- `size` (bytes)
- `createdBy` (user ID)
- `createdOn` (ISO-8601 timestamp)
- `updatedBy` (user ID)
- `uploadedOn` / `updatedOn` (ISO-8601 timestamp)


## Notes and tips

- Keep your access tokens secure. Regenerate or rotate them according to your organization’s policies.
- When paginating, always check for an `offsetToken` and pass it back via the `offset` query parameter until no token is returned.
- Prefer `uploadedOn` to sort by "Most recently changed" since it advances when new versions are added.
- Use `hp-proof-owned-by` if you need to attribute a proof item to a particular user at upload time.