> ## Documentation Index
> Fetch the complete documentation index at: https://docs.proofage.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Consent

> Show the consent text and record the person's acceptance through the API.

The person must accept ProofAge's consent text before any image is uploaded, because the images are biometric data. The hosted widget does this for you; when you [capture in your own UI](/integration/web/custom-ui), you show the text and record the acceptance yourself.

<Warning>
  Until consent is recorded, `POST /v1/verifications/{id}/media` and `POST /v1/verifications/{id}/submit` answer `403 CONSENT_REQUIRED`.
</Warning>

## 1. Fetch the active consent text

```bash theme={null}
curl https://api.proofage.net/v1/consent \
  -H "Accept: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "X-HMAC-Signature: YOUR_HMAC_SIGNATURE"
```

```json 200 OK theme={null}
{
  "id": 3,
  "version": 3,
  "text_sha256": "b5e50967d0ae38c533cb72d2dd5115e27429ff518f06c0d050fee8fb2d834e96",
  "url": "https://app.proofage.net/consent"
}
```

| Field | Description |
| - | - |
| `id` | The consent version's identifier. Send it back when you record the acceptance. |
| `version` | The version number, which grows with each published text. For display only: acceptance uses `id` and `text_sha256`. |
| `text_sha256` | The SHA-256 of the full text. Send it back unchanged; you never compute it yourself. |
| `url` | A hosted HTML page with the full text. Link to it or open it next to your accept button. |

## 2. Show the text

Show the page at `url` before the person accepts. Don't summarise or paraphrase it.

## 3. Record the acceptance

```bash theme={null}
curl -X POST https://api.proofage.net/v1/verifications/550e8400-e29b-41d4-a716-446655440000/consent \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "X-HMAC-Signature: YOUR_HMAC_SIGNATURE" \
  -d '{
    "consent_version_id": 3,
    "text_sha256": "b5e50967d0ae38c533cb72d2dd5115e27429ff518f06c0d050fee8fb2d834e96"
  }'
```

| Field | Type | Required | Description |
| - | - | - | - |
| `consent_version_id` | integer | Yes | The `id` from `GET /v1/consent`. |
| `text_sha256` | string, 64 hex characters | Yes | The `text_sha256` from `GET /v1/consent`. It must match that version. |

```json 200 OK theme={null}
{
  "consent_version_id": 3,
  "consent_accepted_at": "2026-03-19T12:01:00+00:00"
}
```

The hash is what proves which text the person saw: the API accepts it only if it matches the active version's text.

## Retrying

Sending the same `consent_version_id` and `text_sha256` again answers `200` and changes nothing, so a retry after a network error is safe. The version and hash are checked first, though: if the text was replaced in the meantime, the old version answers `409` even on a verification that already has consent. Fetch `GET /v1/consent` again in that case.

## Errors

| HTTP | Body | Cause | What to do |
| - | - | - | - |
| 409 | `{"message": "Consent version is not active"}` | The `consent_version_id` is no longer the active text. | Call `GET /v1/consent` again, show the current text, and record that. |
| 409 | `{"message": "Consent text SHA256 mismatch"}` | `text_sha256` does not match that version. | Send `text_sha256` exactly as `GET /v1/consent` returned it. |
| 422 | `{"message": …, "errors": {…}}` | `consent_version_id` is missing or unknown, or `text_sha256` is not 64 hex characters. | Fix the field named in `errors`. |
| 403 | `{"message": "Access denied to this verification."}` | The verification belongs to another workspace. | Use the key of the workspace that created it. |
| 403 | `CONSENT_REQUIRED` | Sent by the upload and submit endpoints while no consent is recorded. | Record consent first. |

## Next steps

* [Uploading media](/integration/web/uploading-media): the images, and what each must pass.
* [Capture in your own UI](/integration/web/custom-ui): the whole sequence of requests.
* [API authentication](/getting-started/api-authentication): how to sign these requests.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.