> For the complete documentation index, see [llms.txt](https://docs.trezalabs.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.trezalabs.com/ai-gateway/pii-vault.md).

# PII Vault

The PII Vault is an encrypted store for sensitive user records with **consent-gated retrieval**, **GDPR-style deletion**, and a **queryable audit trail**. It complements the redaction proxy: the proxy keeps PII out of LLM prompts, while the vault gives you a compliant place to keep the PII you do need to store.

Every record is encrypted with AES-256-GCM envelope encryption (KMS-backed) before it is written. Plaintext is never stored, and read endpoints return either metadata or the encrypted envelope — decryption happens in your approved environment.

### Authentication & scopes

Vault endpoints authenticate with a Treza API key plus an account header:

```
Authorization: Bearer treza_live_...
x-treza-account: <your account identifier>
```

The `x-treza-account` value must match the account that owns the API key (the identifier shown in the dashboard — your sign-in email or wallet address). Each endpoint requires a specific scope on the key:

| Scope         | Grants                                      |
| ------------- | ------------------------------------------- |
| `pii:ingest`  | Store new records (`pii:write` is an alias) |
| `pii:read`    | List record metadata, retrieve envelopes    |
| `pii:delete`  | Delete records                              |
| `pii:consent` | Grant, revoke, and list consents            |
| `pii:audit`   | Query the access audit log                  |

Create keys with only the scopes each service needs.

### Ingest a record

`POST /api/pii/ingest` — requires `pii:ingest`

```bash
curl -X POST https://trezalabs.com/api/pii/ingest \
  -H "Authorization: Bearer $TREZA_API_KEY" \
  -H "x-treza-account: $TREZA_ACCOUNT" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "passport",
    "payload": { "number": "X1234567", "country": "US" },
    "consentGiven": true,
    "metadata": { "source": "onboarding" }
  }'
```

| Field                | Type          | Notes                                                             |
| -------------------- | ------------- | ----------------------------------------------------------------- |
| `type`               | string        | Required. Your data-type label (e.g. `passport`, `email`)         |
| `payload`            | string/object | Required. Encrypted before storage; objects are JSON-serialized   |
| `consentGiven`       | boolean       | Optional consent flag recorded on the row                         |
| `processorEnclaveId` | string        | Optional. Pins the record to one of your `PII_PROCESSOR` enclaves |
| `metadata`           | object        | Optional non-sensitive metadata                                   |

```json
{
  "piiId": "pii_1718039482_x9y8z7w6v",
  "processorEnclaveId": null,
  "encryption": "AES_256_GCM_KMS_ENVELOPE"
}
```

Every ingest is recorded in the audit log.

### List records

`GET /api/pii/list?account=<your account identifier>` — requires `pii:read`

```bash
curl "https://trezalabs.com/api/pii/list?account=$TREZA_ACCOUNT" \
  -H "Authorization: Bearer $TREZA_API_KEY" \
  -H "x-treza-account: $TREZA_ACCOUNT"
```

Returns metadata only — never ciphertext or plaintext:

```json
{
  "records": [
    {
      "piiId": "pii_1718039482_x9y8z7w6v",
      "dataType": "passport",
      "status": "active",
      "createdAt": "2026-06-10T12:00:00.000Z",
      "processorEnclaveId": null
    }
  ]
}
```

### Retrieve a record (consent-gated)

`POST /api/pii/retrieve` — requires `pii:read`

Retrieval only succeeds when an **active consent** exists for the record's data type and the stated purpose. Denied attempts are recorded in the audit log as violations.

```bash
curl -X POST https://trezalabs.com/api/pii/retrieve \
  -H "Authorization: Bearer $TREZA_API_KEY" \
  -H "x-treza-account: $TREZA_ACCOUNT" \
  -H "Content-Type: application/json" \
  -d '{
    "piiId": "pii_1718039482_x9y8z7w6v",
    "purpose": "kyc-verification"
  }'
```

```json
{
  "piiId": "pii_1718039482_x9y8z7w6v",
  "dataType": "passport",
  "purpose": "kyc-verification",
  "envelope": { "algorithm": "AES_256_GCM_KMS_ENVELOPE", "...": "..." },
  "processorEnclaveId": null,
  "note": "Decrypt envelope inside an approved TEE using KMS."
}
```

The response contains the **encrypted envelope**, not plaintext — decrypt it inside your approved processing environment.

Optionally pass `processorEnclaveId` (and an `attestationDocument`) to require attestation verification of a `PII_PROCESSOR` enclave before the envelope is released; verification failure returns `403`.

| Error                                                  | Meaning                                     |
| ------------------------------------------------------ | ------------------------------------------- |
| `403 No active consent for this data type and purpose` | Grant consent first (logged as a violation) |
| `403 Attestation verification failed`                  | Enclave attestation check did not pass      |
| `404 PII record not found`                             | Unknown, deleted, or not-active record      |

### Consent management

`GET /api/pii/consent?account=<id>` — list consents (requires `pii:consent`) `POST /api/pii/consent` — grant or revoke (requires `pii:consent`)

**Grant** consent for a data type and recipient/purpose:

```bash
curl -X POST https://trezalabs.com/api/pii/consent \
  -H "Authorization: Bearer $TREZA_API_KEY" \
  -H "x-treza-account: $TREZA_ACCOUNT" \
  -H "Content-Type: application/json" \
  -d '{ "dataType": "passport", "recipient": "kyc-verification" }'
```

```json
{ "consentId": "consent_1718039482_q1w2e3r4t", "dataType": "passport", "recipient": "kyc-verification", "active": true }
```

The `recipient` is matched against the `purpose` supplied at retrieval time. Use `any` (or `*`) as a wildcard recipient to allow all purposes for that data type.

**Revoke** a consent:

```bash
curl -X POST https://trezalabs.com/api/pii/consent \
  -H "Authorization: Bearer $TREZA_API_KEY" \
  -H "x-treza-account: $TREZA_ACCOUNT" \
  -H "Content-Type: application/json" \
  -d '{ "revoke": true, "consentId": "consent_1718039482_q1w2e3r4t" }'
```

Grants and revocations are both written to the audit log. Consents expire automatically after three years.

### Delete a record (right to erasure)

`POST /api/pii/delete` — requires `pii:delete`

```bash
curl -X POST https://trezalabs.com/api/pii/delete \
  -H "Authorization: Bearer $TREZA_API_KEY" \
  -H "x-treza-account: $TREZA_ACCOUNT" \
  -H "Content-Type: application/json" \
  -d '{ "piiId": "pii_1718039482_x9y8z7w6v" }'
```

```json
{ "piiId": "pii_1718039482_x9y8z7w6v", "status": "pending_delete", "ttl": 1750705269 }
```

Deletion is designed for GDPR/CCPA erasure requests:

1. The **ciphertext is removed immediately** — the record is unrecoverable from this moment.
2. The row is marked `pending_delete` and the residual metadata is purged automatically within 30 days.
3. The deletion is written to the audit log.

Deleting a non-active record returns `409`; a record you don't own returns `404`.

### Audit log

`GET /api/pii/audit` — requires `pii:audit` when querying by account

Every vault operation (ingest, retrieve, delete, consent grant/revoke) and PII-access events flushed from Treza SDK workflows are queryable:

```bash
curl "https://trezalabs.com/api/pii/audit?account=$TREZA_ACCOUNT&violations=true&limit=50" \
  -H "Authorization: Bearer $TREZA_API_KEY" \
  -H "x-treza-account: $TREZA_ACCOUNT"
```

| Query param     | Description                                                     |
| --------------- | --------------------------------------------------------------- |
| `account`       | Your account identifier (required unless `workflowId` is given) |
| `workflowId`    | Filter to one SDK workflow                                      |
| `workflowRunId` | Filter to one workflow run                                      |
| `violations`    | `true` to return only events flagged as violations              |
| `startDate`     | ISO date lower bound                                            |
| `limit`         | Max events (default 100, cap 500)                               |

```json
{
  "summary": { "total": 2, "violations": 1, "workflows": ["wf_onboarding"] },
  "events": [ { "eventId": "pii_...", "hadViolation": true, "timestamp": "..." } ]
}
```

Audit events are retained for 90 days.

{% hint style="info" %}
The PII Vault audit log (`/api/pii/audit`) tracks access to **stored records**. The redaction proxy has its own log (`GET /api/redact/log`) tracking entities redacted from LLM traffic — see the [Quickstart](/ai-gateway/quickstart.md#6-view-the-audit-log).
{% endhint %}
