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

# Pinata

> IPFS pinning service for zkStorage file hosting

## Overview

Pinata provides IPFS pinning services that zkStorage uses to store encrypted files. Files are encrypted client-side before upload, then pinned to IPFS via Pinata's API.

## How It Works

1. **Encrypt:** Files encrypted client-side with AES-256-GCM
2. **Upload:** Encrypted blob uploaded to Pinata API
3. **Pin:** Pinata pins the file to IPFS network
4. **CID:** Returns Content Identifier (CID) for retrieval
5. **Download:** Fetch via Pinata gateway, decrypt client-side

## Features

1. **Fast Uploads** - Direct upload to Pinata with retry logic
2. **Gateway Access** - Downloads via gateway.pinata.cloud
3. **Metadata Storage** - Separate CID for file metadata
4. **Multi-Gateway Fallback** - Cloudflare and ipfs.io as backup

## Integration with zkStorage

zkStorage uses Pinata for all IPFS operations:

```
┌─────────────┐      ┌─────────────┐      ┌─────────────┐
│   Client    │      │   zkTerm    │      │   Pinata    │
│  (Browser)  │      │   Server    │      │    IPFS     │
├─────────────┤      ├─────────────┤      ├─────────────┤
│ 1. Encrypt  │ ───> │ 2. Upload   │ ───> │ 3. Pin      │
│    file     │      │    to API   │      │    to IPFS  │
│             │ <─── │ 4. Return   │ <─── │ 5. Return   │
│             │      │    CID      │      │    CID      │
└─────────────┘      └─────────────┘      └─────────────┘
```

## Terminal Commands

zkStorage commands that use Pinata:

```bash theme={null}
zk storage upload              # Upload → Pinata → IPFS
zk storage download <file-id>  # Pinata Gateway → Decrypt
zk storage list                # List files (metadata from DB)
```

## API Details

### Upload to Pinata

zkTerm uploads encrypted files using Pinata's pinFileToIPFS endpoint:

```typescript theme={null}
const response = await fetch('https://api.pinata.cloud/pinning/pinFileToIPFS', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${PINATA_JWT}`,
  },
  body: formData,
});

const { IpfsHash } = await response.json();
// IpfsHash is the CID, e.g., "QmXyz123..."
```

### Download from Gateway

Downloads use the Pinata gateway with fallbacks:

```typescript theme={null}
const gateways = [
  'https://gateway.pinata.cloud/ipfs',
  'https://cloudflare-ipfs.com/ipfs',
  'https://ipfs.io/ipfs',
];

const response = await fetch(`${gateway}/${cid}`);
```

## File Structure

Each zkStorage upload creates two IPFS objects:

| Object         | Content                      | CID Example   |
| -------------- | ---------------------------- | ------------- |
| Encrypted File | AES-256-GCM encrypted data   | `QmXyz123...` |
| Metadata       | IV, salt, original name/size | `QmAbc456...` |

**Metadata JSON:**

```json theme={null}
{
  "originalName": "document.pdf",
  "originalSize": 1234567,
  "iv": "base64...",
  "salt": "base64...",
  "iterations": 100000,
  "zkEnabled": true,
  "commitment": "poseidon-hash..."
}
```

## Error Handling

| Error                       | Cause                  | Solution                      |
| --------------------------- | ---------------------- | ----------------------------- |
| `PINATA_JWT not configured` | Missing API key        | Set PINATA\_JWT env var       |
| `Upload failed: 401`        | Invalid JWT            | Regenerate Pinata API key     |
| `Gateway timeout`           | IPFS propagation delay | Retry or use fallback gateway |
| `CID not found`             | File unpinned          | Re-upload the file            |

## Retry Logic

Uploads include automatic retry with exponential backoff:

```typescript theme={null}
for (let attempt = 1; attempt <= 3; attempt++) {
  try {
    return await uploadToPinata(buffer, filename);
  } catch (error) {
    await sleep(1000 * attempt); // 1s, 2s, 3s
  }
}
```

## Timeouts

| Operation      | Timeout    |
| -------------- | ---------- |
| File upload    | 60 seconds |
| Gateway fetch  | 30 seconds |
| Metadata fetch | 30 seconds |

## Environment Variables

| Variable     | Description                     |
| ------------ | ------------------------------- |
| `PINATA_JWT` | Pinata API JWT token (required) |

## Getting a Pinata API Key

1. Create account at [pinata.cloud](https://pinata.cloud)
2. Go to API Keys section
3. Create new key with `pinFileToIPFS` permission
4. Copy JWT token to `PINATA_JWT` environment variable

## Pricing

Pinata offers:

* **Free tier:** 1GB storage, 100 pins
* **Starter:** \$20/month, 25GB storage
* **Professional:** Custom pricing

zkStorage uses minimal storage since only encrypted blobs are stored.

## Migration Notes

zkStorage previously used NFT.Storage (deprecated June 2024). Migration to Pinata provides:

1. Better upload reliability
2. Faster gateway access
3. Active maintenance and support
