# Disclose an attribute

`POST /functions/v1/disclose-claims`

Resolve requested fields into a value, a derived boolean claim where the raw data never leaves the server, or a document behind a revocable consent token.

## Three disclosure types

| disclosure_type | What comes back |
| --- | --- |
| value | A plain value |
| zk_proof | A derived boolean claim — age_over_21: true — where the raw date of birth never leaves the server |
| document | A signed URL wrapped in a consent-token envelope |

## Body

| Field | Type | Notes |
| --- | --- | --- |
| zk_proof_audit_id | string | required |
| merchant_id | string | required |
| transaction_type | string | required |
| requestedFields | array | { key, disclosure_type, requires_kyc?, circuit_id?, public_input? } |
| biometric_attestation | object | { liveness_passed, vrc_confidence, device_pubkey_pem? } |
| ttl_seconds | integer | How long the disclosure stays fetchable |

```
{
  "zk_proof_audit_id": "zk_71ac33",
  "merchant_id": "mrc_9f2c",
  "transaction_type": "onboarding",
  "requestedFields": [
    { "key": "age_over_21", "disclosure_type": "zk_proof", "circuit_id": "age_v1", "public_input": "21" },
    { "key": "full_name", "disclosure_type": "value" }
  ],
  "biometric_attestation": { "liveness_passed": true, "vrc_confidence": 0.87 },
  "ttl_seconds": 300
}
```

## Consent is revocable, and revocation is immediate

The call ends with an atomic write to the consent ledger. The merchant validates the disclosure with `consent_token`; `revoke-consent` kills the token and the fetch becomes a `403`.

Field keys are per-merchant scope and are not a published catalogue yet. Document the shape, not a list that would go stale.
