# ProofPack Mint API

The ProofPack Mint API lets **you** (the human, using your API key) generate **ProofPacks**: selective-disclosure proofs that reveal only chosen identity fields to a specific agent wallet. You call the API and pass the agent’s wallet address in the request. That wallet must be delegated to you via an IsDelegate attestation chain (you → agent, or you → agent → sub-agent → …). The API walks the full chain back to your human root and only mints if the chain is valid—so you can mint for a direct delegate or for a sub-agent several hops deep.

For the full user journey from attested identity to a JWT with a claim like nationality, see [Getting a ProofPack JWT with a Nationality Claim](https://docs.zipwire.io/zipwire-attest/getting-a-proofpack-jwt-with-nationality).

**Base path:** `/api/v1/proofpack`\
**Category:** [Zipwire Attest](https://docs.zipwire.io/api#zipwire-attest)

**Features:**

* Generate selective-disclosure proofs for delegated agent wallets.
* Choose which identity fields to reveal (e.g. nationality, date\_of\_birth).
* Output as **JWS** (JSON) or **JWT** (compact string).
* All responses use HTTP 200; check the `success` field in the body for success or error.

***

## Authentication

Every request must include your API key.

**Header:**

```
X-API-Key: your-api-key-here
```

**If the API key is missing or invalid**, the response is still 200 OK with an error in the body:

```json
{
  "success": false,
  "code": "InvalidApiKey",
  "message": "Invalid or missing API key"
}
```

***

## Response format

All responses use the same shape. Use `success` to decide whether the call succeeded.

**Success:**

```json
{
  "success": true,
  "code": null,
  "message": "ProofPack generated successfully",
  "proofPack": "eyJhbGciOiJFUzI1NksiLCJ0eXAiOiJKV1MifQ...",
  "attestationUid": "0x1234567890abcdef...",
  "agentWallet": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
  "selectedFields": ["nationality", "date_of_birth"]
}
```

**Error:**

```json
{
  "success": false,
  "code": "AgentNotDelegated",
  "message": "Agent wallet 0xabc... has no valid IsDelegate attestation",
  "proofPack": null,
  "attestationUid": null,
  "agentWallet": null,
  "selectedFields": null
}
```

Some error responses include a top-level **suggestions** field (object) to help you fix the request. For `InvalidFieldSelection`, the response body includes **suggestions** with an **available\_fields** array listing the valid field names for your account.

***

## Endpoint: Mint ProofPack

**POST** `/api/v1/proofpack/mint`

Generates a ProofPack for a single delegated agent wallet.

### Request body

```json
{
  "agentWallet": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
  "selectedFields": ["nationality", "date_of_birth"],
  "format": "JWT"
}
```

| Field            | Type      | Required | Description                                                                                                                                                                                                                                                                                                              |
| ---------------- | --------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `agentWallet`    | string    | Yes      | Ethereum wallet address (0x-prefixed) that is delegated to you. Can be a direct delegate or a sub-agent multiple hops down the chain (e.g. Human → Agent1 → Agent2 → Agent3); the API walks the chain back to your human attestation.                                                                                    |
| `selectedFields` | string\[] | No       | Optional. Field keys to reveal (e.g. `nationality`, `date_of_birth`). If omitted or empty, the proof is minted with no identity fields revealed. If provided, must be a non-empty list of keys that exist in your identity data. See [Available fields](#selective-disclosure) for keys from Yoti document verification. |
| `format`         | string    | No       | `"JWS"` (JSON) or `"JWT"` (compact). Default: `"JWS"`.                                                                                                                                                                                                                                                                   |

### Validation

* **agentWallet:** Required; must be a valid Ethereum address.
* **selectedFields:** Optional. If omitted or empty, the proof is minted with no identity fields revealed. If provided, must be a non-empty array; each field must exist in your identity data. Field names are case-sensitive. If you request a field that doesn’t exist, the error message lists the invalid field names you sent, and **suggestions.available\_fields** in the response lists the valid field names for your account.

### Success response (200)

```json
{
  "success": true,
  "code": null,
  "message": "ProofPack generated successfully",
  "proofPack": "eyJwYXlsb2FkIjoiZXlK...",
  "attestationUid": "0x8af15e65888f2e3b487e536a4922e277dcfe85b4b18187b0cf9afdb802ba6bb6",
  "agentWallet": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
  "selectedFields": ["nationality", "date_of_birth"]
}
```

### Example errors (all 200 OK, with body indicating failure)

**Invalid API key:**

```json
{
  "success": false,
  "code": "InvalidApiKey",
  "message": "Invalid or missing API key"
}
```

**Agent not delegated:**

```json
{
  "success": false,
  "code": "AgentNotDelegated",
  "message": "Agent wallet 0xabcdef... has no valid IsDelegate attestation"
}
```

**Invalid field:**

```json
{
  "success": false,
  "code": "InvalidFieldSelection",
  "message": "Invalid fields: nonexistent_field",
  "suggestions": {
    "available_fields": ["date_of_birth", "family_name", "given_names", "nationality"]
  }
}
```

The message lists the field names you requested that are not in your Merkle tree. The response includes a **suggestions** object with **available\_fields** (array of valid field names for your account) so you can correct your request.

***

## Error codes

| Code                               | Description                                                                                                                                                             |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `InvalidApiKey`                    | API key missing or invalid.                                                                                                                                             |
| `NoHumanAttestation`               | Your account has no identity attestation.                                                                                                                               |
| `AgentNotDelegated`                | The agent wallet has no valid IsDelegate attestation to a human.                                                                                                        |
| `DelegationPointsToDifferentHuman` | The agent is delegated to someone else, not you.                                                                                                                        |
| `MerkleTreeNotFound`               | Identity data for your account could not be found.                                                                                                                      |
| `InvalidFieldSelection`            | One or more requested fields don’t exist; the message lists the invalid names you sent; **suggestions.available\_fields** lists the valid field names for your account. |
| `ProofGenerationFailed`            | Proof generation failed.                                                                                                                                                |
| `InternalError`                    | Unexpected server error.                                                                                                                                                |

***

## Output formats

**JWS (default)**\
Set `"format": "JWS"` or omit `format`. The `proofPack` value is a JSON object with `payload` and `signatures` (RFC 7515 JSON serialization). Use this when you need to parse or validate the full proof structure.

**JWT**\
Set `"format": "JWT"`. The `proofPack` value is a compact string: `header.payload.signature`. Use this when you need a short, URL-safe string (e.g. in headers or URLs).

***

## How delegation is checked

Before minting a ProofPack, the API walks the delegation chain from the wallet you passed to your human root:

1. Looks up IsDelegate attestations for the agent wallet (the one in your request).
2. Follows **refUID** link by link (e.g. SubAgent → … → Agent → Human). The chain can be multiple hops deep; the verifier supports this with depth and cycle safeguards.
3. Verifies the chain reaches a valid human identity and that identity is the same as the owner of the API key.
4. If any step fails, returns the appropriate error code (e.g. `AgentNotDelegated`, `DelegationPointsToDifferentHuman`).

So you can call the Mint API with a sub-agent’s wallet address and receive a ProofPack for that sub-agent—the API traces the full chain back to you.

***

## Selective disclosure

Your identity data is represented in a Merkle tree. When you provide `selectedFields`, the ProofPack reveals only those fields; other fields are committed by hash and not exposed. If you omit `selectedFields` (or pass an empty array), the proof is minted with no identity fields revealed.

**Available fields** come from Yoti document verification (e.g. passport or driving licence). Typical keys include:

* **Personal:** `full_name`, `given_names`, `family_name`, `nationality`, `date_of_birth`, `place_of_birth`, `gender`
* **Document:** `document_number`, `issuing_country`, `document_type`, `expiration_date`, `date_of_issue`, `issuing_authority`
* **Technical / metadata:** `mrz`, `document_template`, `idsp_id`, `report_id`, `report_date_utc`

Exact fields depend on your stored identity and document type. If you send an invalid field name, the error response lists the invalid fields you requested and includes **suggestions.available\_fields** with the list of valid field names for your account.

***

## Example request

```bash
curl -X POST "https://zipwire.io/api/v1/proofpack/mint" \
  -H "X-API-Key: your-api-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "agentWallet": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
    "selectedFields": ["nationality", "date_of_birth"],
    "format": "JWT"
  }'
```

***

## Best practices

1. **Minimal disclosure:** Only request fields the agent actually needs.
2. **Check `success`:** Always look at the `success` field before using `proofPack` or other result fields.
3. **Handle errors:** Use the `code` and `message` fields to handle invalid keys, undelegated agents, and invalid fields.
4. **Verify on the agent side:** The agent should verify the ProofPack with the ProofPack library before trusting the contents.

For verification and integration patterns, see [ProofPack & Agent Delegation](https://docs.zipwire.io/tools-and-integrations/proofpack-agent-delegation) and [ProofPack Examples](https://docs.zipwire.io/tools-and-integrations/proofpack-agent-delegation/proofpack-examples). For the end-to-end journey to obtain a JWT ProofPack (attestation → delegation → mint), see [Getting a ProofPack JWT with a Nationality Claim](https://docs.zipwire.io/zipwire-attest/getting-a-proofpack-jwt-with-nationality).
