IPFS API¶
API endpoints for uploading and retrieving files from IPFS via Pinata.
Endpoints¶
| Endpoint | Method | Description |
|---|---|---|
/api/ipfs/upload | POST | Upload a file to IPFS |
/api/ipfs/metadata | POST | Upload JSON metadata |
/api/ipfs/pin/{cid} | GET | Check pin status |
Upload File¶
Upload a file to IPFS and get the content hash (CID).
Request¶
Form Data¶
| Field | Type | Required | Description |
|---|---|---|---|
file | File | Yes | File to upload |
name | string | No | Custom name for the pin |
Response¶
{
"ok": true,
"cid": "QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco",
"url": "ipfs://QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco",
"gateway": "https://gateway.pinata.cloud/ipfs/QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco",
"size": 102400
}
Example¶
const formData = new FormData()
formData.append('file', imageFile)
formData.append('name', 'model-cover-image')
const response = await fetch('/api/ipfs/upload', {
method: 'POST',
body: formData
})
const { cid, url } = await response.json()
// url = "ipfs://QmXoy..."
Upload Metadata¶
Upload JSON metadata to IPFS. Useful for model and agent metadata.
Request¶
Body¶
{
"name": "Crypto Sentiment Analyzer",
"description": "Analyzes sentiment of crypto news...",
"category": "sentiment-analysis",
"coverImage": "ipfs://QmCover...",
"modelType": "sentiment-analysis",
"inputFormat": "text",
"outputFormat": "json",
"artifacts": [
{
"name": "model-weights",
"cid": "QmWeights...",
"size": 50000000
}
],
"licensePolicy": {
"perpetual": true,
"subscription": true,
"apiAccess": true,
"downloadAccess": true
}
}
Response¶
{
"ok": true,
"cid": "QmMetadata...",
"url": "ipfs://QmMetadata...",
"gateway": "https://gateway.pinata.cloud/ipfs/QmMetadata..."
}
Check Pin Status¶
Verify a file is pinned on IPFS.
Request¶
Path Parameters¶
| Parameter | Type | Description |
|---|---|---|
cid | string | IPFS content hash |
Response¶
{
"ok": true,
"pinned": true,
"cid": "QmXoy...",
"size": 102400,
"createdAt": "2024-12-01T00:00:00Z"
}
IPFS Gateway URLs¶
WasiAI uses Pinata's gateway for IPFS content:
Converting IPFS URLs¶
function ipfsToHttp(ipfsUrl: string): string {
if (ipfsUrl.startsWith('ipfs://')) {
const cid = ipfsUrl.replace('ipfs://', '')
return `https://gateway.pinata.cloud/ipfs/${cid}`
}
return ipfsUrl
}
File Size Limits¶
| File Type | Max Size |
|---|---|
| Images | 5MB |
| Model artifacts | 100MB |
| Metadata JSON | 1MB |
| Total per upload | 100MB |
Supported File Types¶
Images¶
- PNG, JPG, JPEG, WebP, GIF, SVG
Documents¶
- PDF, MD, TXT
Model Files¶
- .bin, .pt, .onnx, .safetensors
- .json, .yaml, .yml
Code Examples¶
Upload Cover Image¶
async function uploadCoverImage(file: File): Promise<string> {
const formData = new FormData()
formData.append('file', file)
formData.append('name', `cover-${Date.now()}`)
const response = await fetch('/api/ipfs/upload', {
method: 'POST',
body: formData
})
const { url } = await response.json()
return url // "ipfs://Qm..."
}
Upload Model Metadata¶
async function uploadMetadata(metadata: ModelMetadata): Promise<string> {
const response = await fetch('/api/ipfs/metadata', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(metadata)
})
const { url } = await response.json()
return url // "ipfs://Qm..."
}
Fetch IPFS Content¶
async function fetchIPFSContent(cid: string): Promise<any> {
const response = await fetch(
`https://gateway.pinata.cloud/ipfs/${cid}`
)
return response.json()
}
Error Responses¶
File Too Large (413)¶
Invalid File Type (400)¶
Upload Failed (500)¶
Rate Limits¶
| Endpoint | Limit | Window |
|---|---|---|
/api/ipfs/upload | 10 requests | 1 minute |
/api/ipfs/metadata | 10 requests | 1 minute |
/api/ipfs/pin/* | 30 requests | 1 minute |