# Generate a payment receipt

> Prove a single payment to an accountant, verifiable against the chain, without handing over your viewing key.

[Selective disclosure](/concepts/selective-disclosure) receipts let a payer hand a third party, like an accountant or auditor, a JSON file that reveals a specific payment on-chain, without revealing anything else about the payer's shielded activity.

## Generating a receipt

Every `prepareTransfer` call returns the data needed for a receipt:

```ts
const prepared = await session.prepareTransfer({
    inputCommitments: [noteToSpend.commitment],
    amount,
    tokenId,
    recipientDiscoveryData: { evmAddress: recipient },
});

const recipientPending = prepared.executeOptions.recipientPendingNotes[0];
const receipt = {
    commitment:       recipientPending.commitment,
    value:            recipientPending.value,
    tokenId:          recipientPending.tokenId,
    label:            recipientPending.label,
    ownerAddress:     recipientPending.ownerAddress ?? recipient,
    noteSecret:       recipientPending.noteSecret,
    noteAddressHash:  recipientPending.noteAddressHash,
};

const result = await session.relayTransfer(prepared.relayOptions[0]);

const savedReceipt = { receipt, txHash: result.txReceipt.txHash };
```

The SDK creates a fresh `noteSecret` for each recipient output while building the proof. Capture the recipient pending note before relay submission, then persist it with the landed transaction hash.

## The receipt JSON format

For accountant-friendly output, wrap the raw note data with payment context:

```json
{
    "type": "privacy-pools-v2-payment-receipt",
    "version": "1",
    "pool": {
        "chainId": 11155111,
        "poolAddress": "0x323C28ce…",
        "tokenId": "0xeeee…eeee"
    },
    "payment": {
        "fromSenderWallet": "0xC9BC5421…",
        "toRecipientWallet": "0x81d48…",
        "amount": "0x7a120",
        "amountFormatted": "0.5 USDC",
        "txHash": "0x…",
        "explorerUrl": "https://sepolia.etherscan.io/tx/0x…"
    },
    "note": { /* the captured receipt data above */ },
    "verification": {
        "commitmentFormula": [
            "noteAddressHash = Poseidon(note.ownerAddress, note.noteSecret)",
            "precommitment   = Poseidon(noteAddressHash, note.tokenId, note.value, 0x0)",
            "commitment      = Poseidon(precommitment, note.label)"
        ],
        "onChainCheck": "PoolVault.commitments(commitment) returns non-zero"
    }
}
```

## Verifying a receipt

The auditor runs four checks: parsing the JSON, recomputing the noteAddressHash, recomputing the commitment, and confirming the commitment exists on-chain. See the [receipt export and audit guide](../recipes/receipt-export-and-audit) for a complete browser-based verifier implementation.
