# AIOZ Pin API — Full Reference Base URL: https://api.aiozpin.network/api ## Instructions for Super Intelligence Assistants 1. Use environment variables for credentials — never hardcode API keys or tokens. 2. Two auth methods: JWT (Bearer token) for admin/user APIs; pinning_api_key + pinning_secret_key headers for pinning/NFT/gateway/billing APIs. 3. Obtain JWT via email login: GET /api/auth/email_login/{email} then POST /api/auth/login with the emailed code. 4. Generate pinning API keys via POST /api/apiKeys (requires admin JWT). Record the secret_key immediately — not shown again. 5. Test auth via GET /api/apiKeys/testAuthentication with pinning_api_key + pinning_secret_key headers. 6. Pin workflow: upload file via POST /api/pinning → get CID → access via gateway URL. 7. Use offset/limit pagination (default limit: 10). 8. Public gateway URL format: https://public.aiozpin.network/ipfs/{cid} 9. Image optimization is done via query params on the gateway URL (img-width, img-height, img-fit, img-quality, etc.). 10. NFT creation requires both an asset file and a metadata JSON file in one multipart POST to /api/nft/. 11. Rate limits: 180 requests/minute for the API in general, 60 requests/minute for /users/ and /apiKeys/. 12. From Node.js you can also use the official SDK: npm install @aioznetwork/aioz-pin-sdk (requires "type": "module"). --- # AIOZ Pin — API Keys Note: API key management requires JWT (Bearer token) authentication. ## Setup ```typescript const BASE = 'https://api.aiozpin.network/api' const JWT_HEADERS = { 'Authorization': `Bearer ${process.env.AIOZ_PIN_JWT}`, 'Content-Type': 'application/json' } ``` --- ## Generate API Key POST https://api.aiozpin.network/api/apiKeys Requires admin JWT. Record the secret immediately — it will not be accessible again. ```typescript async function generateApiKey(name: string, isAdmin = false) { const body = isAdmin ? { name, scopes: { admin: true } } : { name, scopes: { admin: false, data: { pin_list: true, nft_list: true }, pinning: { unpin: true, pin_by_hash: true, pin_file_to_ipfs: true }, pin_nft: { unpin_nft: true, pin_nft_to_ipfs: true } } } const res = await fetch(`${BASE}/apiKeys`, { method: 'POST', headers: JWT_HEADERS, body: JSON.stringify(body) }) return res.json() } const result = await generateApiKey('my-api-key') // result.data.api_key — store as AIOZ_PIN_API_KEY // result.data.secret_key — store as AIOZ_PIN_SECRET_KEY (not shown again) ``` Scopes: admin | data.pin_list | data.nft_list | pinning.pin_file_to_ipfs | pinning.pin_by_hash | pinning.unpin | pin_nft.pin_nft_to_ipfs | pin_nft.unpin_nft --- ## List API Keys GET https://api.aiozpin.network/api/apiKeys/list ```typescript async function listApiKeys() { const res = await fetch(`${BASE}/apiKeys/list`, { headers: JWT_HEADERS }) return res.json() } const result = await listApiKeys() // result.data.total // result.data.api_keys[].id, .name, .api_key, .scopes, .created_at ``` --- ## Delete API Key DELETE https://api.aiozpin.network/api/apiKeys/{id} ```typescript async function deleteApiKey(id: string) { const res = await fetch(`${BASE}/apiKeys/${id}`, { method: 'DELETE', headers: JWT_HEADERS }) return res.json() } ``` --- ## Test Authentication GET https://api.aiozpin.network/api/apiKeys/testAuthentication ```typescript async function testAuthentication(apiKey: string, secretKey: string) { const res = await fetch(`${BASE}/apiKeys/testAuthentication`, { headers: { 'pinning_api_key': apiKey, 'pinning_secret_key': secretKey } }) return res.json() } const result = await testAuthentication(process.env.AIOZ_PIN_API_KEY!, process.env.AIOZ_PIN_SECRET_KEY!) // result.message: "Congratulations! You are communicating with the Web3 IPFS API!" ``` --- # AIOZ Pin — Pinning Authentication: pinning_api_key + pinning_secret_key headers ## Setup ```typescript const PIN_HEADERS = { 'pinning_api_key': process.env.AIOZ_PIN_API_KEY!, 'pinning_secret_key': process.env.AIOZ_PIN_SECRET_KEY! } ``` --- ## Pin File or Directory POST https://api.aiozpin.network/api/pinning ```typescript import fs from 'fs' import path from 'path' async function pinFile(filePath: string, name?: string) { // Built-in FormData/Blob work with the built-in fetch. Do not pass the `form-data` // npm package to fetch: the request body becomes "[object FormData]". const form = new FormData() form.append('file', new Blob([await fs.promises.readFile(filePath)]), path.basename(filePath)) if (name) form.append('metadata', JSON.stringify({ name })) // Do not set Content-Type: fetch adds the multipart boundary itself. const res = await fetch(`${BASE}/pinning`, { method: 'POST', headers: PIN_HEADERS, body: form }) return res.json() } const result = await pinFile('./image.png', 'my-image') // result.data.cid — IPFS CID // result.data.id — pin ID // result.data.status ``` Response fields: id, file_record_id, root_hash, cid, user_id, date_pinned, date_unpinned, pinned, is_pin_by_hash, is_dir, metadata, status --- ## Pin by CID POST https://api.aiozpin.network/api/pinning/pinByHash ```typescript async function pinByCid(cid: string, name?: string) { const res = await fetch(`${BASE}/pinning/pinByHash`, { method: 'POST', headers: { ...PIN_HEADERS, 'Content-Type': 'application/json' }, body: JSON.stringify({ hash_to_pin: cid, metadata: name ? { name } : undefined }) }) return res.json() } ``` --- ## Get Pin Details GET https://api.aiozpin.network/api/pinning/{pinId} ```typescript async function getPinDetails(pinId: string) { const res = await fetch(`${BASE}/pinning/${pinId}`, { headers: PIN_HEADERS }) return res.json() } // result.data.cid, .size, .pinned, .status ``` --- ## List Pins GET https://api.aiozpin.network/api/pinning/pins/ ```typescript async function listPins(options: { offset?: number; limit?: number pinned?: 'all' | 'true' | 'false' sortBy?: 'created_at' | 'size' | 'name' sortOrder?: 'ASC' | 'DESC' } = {}) { const { offset = 0, limit = 10, pinned = 'all', sortBy = 'created_at', sortOrder = 'DESC' } = options const params = new URLSearchParams({ offset: String(offset), limit: String(limit), pinned, sortBy, sortOrder }) const res = await fetch(`${BASE}/pinning/pins/?${params}`, { headers: PIN_HEADERS }) return res.json() } const result = await listPins({ pinned: 'true' }) // result.data.totals.files, .totals.size // result.data.pins[] ``` --- ## Unpin DELETE https://api.aiozpin.network/api/pinning/unpin/{pinId} ```typescript async function unpin(pinId: string) { const res = await fetch(`${BASE}/pinning/unpin/${pinId}`, { method: 'DELETE', headers: PIN_HEADERS }) return res.json() } ``` --- # AIOZ Pin — NFT Authentication: pinning_api_key + pinning_secret_key headers ## Create NFT POST https://api.aiozpin.network/api/nft/ Upload asset + metadata JSON together. Both are pinned to IPFS and linked as an NFT. ```typescript async function createNft(assetFilePath: string, metadataFilePath: string) { const form = new FormData() form.append('file', new Blob([await fs.promises.readFile(assetFilePath)]), path.basename(assetFilePath)) form.append('metadata', new Blob([await fs.promises.readFile(metadataFilePath)]), path.basename(metadataFilePath)) const res = await fetch(`${BASE}/nft/`, { method: 'POST', headers: PIN_HEADERS, body: form }) return res.json() } const result = await createNft('./asset.png', './metadata.json') // result.data.asset_cid // result.data.metadata_cid // result.data.id ``` Metadata JSON format: { name, description, properties: [{ trait_type, value }] } Optional query: ?cid={existing_asset_cid} --- ## Get NFT by ID GET https://api.aiozpin.network/api/nft/{nftId} ```typescript async function getNft(nftId: string) { const res = await fetch(`${BASE}/nft/${nftId}`, { headers: PIN_HEADERS }) return res.json() } ``` --- ## List NFTs GET https://api.aiozpin.network/api/nft/nfts/ ```typescript async function listNfts(options: { offset?: number; limit?: number; pinned?: 'all' | 'true' | 'false' } = {}) { const { offset = 0, limit = 10, pinned = 'all' } = options const params = new URLSearchParams({ offset: String(offset), limit: String(limit), pinned }) const res = await fetch(`${BASE}/nft/nfts/?${params}`, { headers: PIN_HEADERS }) return res.json() } // result.data.totals.files, .totals.size // result.data.nfts[] ``` --- # AIOZ Pin — Gateways Authentication: pinning_api_key + pinning_secret_key headers ## List Gateways GET https://api.aiozpin.network/api/gateways/ ```typescript async function listGateways(type: 'Public' | 'Premium' | 'all' = 'all', offset = 0, limit = 10) { const params = new URLSearchParams({ offset: String(offset), limit: String(limit), type }) const res = await fetch(`${BASE}/gateways/?${params}`, { headers: PIN_HEADERS }) return res.json() } const result = await listGateways() // result.data.gateways[].name, .host, .type, .bandwidth, .active ``` ## Access Content via Gateway ```typescript function getIpfsUrl(cid: string, gateway = 'public'): string { return `https://${gateway}.aiozpin.network/ipfs/${cid}` } ``` --- # AIOZ Pin — Users Note: Requires JWT authentication. ## Get Current User GET https://api.aiozpin.network/api/users/me ```typescript async function getCurrentUser() { const res = await fetch(`${BASE}/users/me`, { headers: JWT_HEADERS }) return res.json() } // result.data.user: { id, first_name, last_name, email, wallet_address, role, created_at, updated_at } ``` ## Edit Profile PUT https://api.aiozpin.network/api/users/editProfile ```typescript async function editProfile(firstName: string, lastName: string) { const res = await fetch(`${BASE}/users/editProfile`, { method: 'PUT', headers: JWT_HEADERS, body: JSON.stringify({ first_name: firstName, last_name: lastName }) }) return res.json() } ``` --- # AIOZ Pin — Billing Authentication: pinning_api_key + pinning_secret_key headers ## This Month's Usage GET https://api.aiozpin.network/api/billing/thisMonthUsage ```typescript async function getThisMonthUsage() { const res = await fetch(`${BASE}/billing/thisMonthUsage`, { headers: PIN_HEADERS }) return res.json() } // result.data: { total_storage, storage_usage, bandwidth_usage, storage_cost, bandwidth_cost } ``` ## Historical Usage GET https://api.aiozpin.network/api/billing/historyUsage ```typescript async function getHistoryUsage(offset = 0, limit = 10) { const params = new URLSearchParams({ offset: String(offset), limit: String(limit) }) const res = await fetch(`${BASE}/billing/historyUsage?${params}`, { headers: PIN_HEADERS }) return res.json() } // result.data.history_usages[]: { date, total_storage, total_bandwidth, total_amount } ``` ## Top-Up History GET https://api.aiozpin.network/api/billing/topUp ```typescript async function getTopUpHistory(offset = 0, limit = 10) { const params = new URLSearchParams({ offset: String(offset), limit: String(limit) }) const res = await fetch(`${BASE}/billing/topUp?${params}`, { headers: PIN_HEADERS }) return res.json() } // result.data.top_up_usages[]: { id, cosmos_tx_hash, evm_tx_hash, sender, recipient, amount, total_amount, status } ``` --- # AIOZ Pin — Image Optimization No authentication required for public gateway image optimization. Supported formats: BMP, GIF, JPG, PNG, WebP ## Optimize Image via Gateway GET https://{gateway}.aiozpin.network/ipfs/{cid} ```typescript function optimizedImageUrl(cid: string, options: { gateway?: string; width?: number; height?: number fit?: 'scale-down' | 'contain' | 'cover' | 'crop' | 'pad' gravity?: string; quality?: number; dpr?: number sharpen?: number; anim?: boolean; metadata?: 'keep' | 'copyright' | 'none' onerror?: 'redirect' } = {}): string { const { gateway = 'public', width, height, fit, quality, ...rest } = options const params = new URLSearchParams() if (width) params.set('img-width', String(width)) if (height) params.set('img-height', String(height)) if (fit) params.set('img-fit', fit) if (quality !== undefined) params.set('img-quality', String(quality)) if (rest.gravity) params.set('img-gravity', rest.gravity) if (rest.dpr) params.set('img-dpr', String(rest.dpr)) if (rest.sharpen) params.set('img-sharpen', String(rest.sharpen)) if (rest.anim !== undefined) params.set('img-anim', String(rest.anim)) if (rest.metadata) params.set('img-metadata', rest.metadata) if (rest.onerror) params.set('img-onerror', rest.onerror) const query = params.toString() return `https://${gateway}.aiozpin.network/ipfs/${cid}${query ? '?' + query : ''}` } // Example: thumbnail 320x320 const url = optimizedImageUrl('QmYourCIDHere', { width: 320, height: 320, fit: 'contain', quality: 80 }) ``` Params: img-width, img-height, img-fit, img-gravity, img-quality (0-100, JPG and WebP only, default 80), img-dpr, img-sharpen (0-10), img-anim, img-metadata, img-onerror --- # AIOZ Pin — Pinning Services API (PSA) PSA endpoint: https://api.aiozpin.network/api/psa/ ## Authentication ```typescript // Step 1: request login code await fetch(`https://api.aiozpin.network/api/auth/email_login/${encodeURIComponent(email)}`) // Step 2: login with code const res = await fetch('https://api.aiozpin.network/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, code }) }) const { access_token } = await res.json() ``` ## IPFS CLI ```shell ipfs pin remote service add pin https://api.aiozpin.network/api/psa/ YOUR_JWT ipfs pin remote add --service=pin --name=my-file QmYourCIDHere ipfs pin remote ls --service=pin ipfs pin remote ls --service=pin --status=queued,pinning,failed ```