· Nacho Coll · Tutorials · 9 min branja
IPFS Upload API — Popoln vodič za razvijalce
Naučite se naložiti datoteke na IPFS prek REST API-ja. Popolni primeri kode v JavaScriptu, Node.js in curl. Naložite JSON, slike, uporabite podpisane žetone za nalaganje s strani odjemalca.

IPFS Upload API — Popoln vodič za razvijalce
Nalaganje datotek na IPFS bi moralo biti tako preprosto kot izvedba POST zahteve. V tem vodiču boste storili ravno to — naložili boste JSON dokumente, slike in PDF-je na IPFS z ničemer drugim kot fetch() in API ključem. Na koncu boste imeli popolno Node.js skripto, ki nalaga vsebino, izpisuje datoteke, pridobiva metapodatke in generira podpisane žetone za varno nalaganje s strani odjemalca. Novi na IPFS? Začnite s Kaj je IPFS Pinning?, da razumete osnove, preden se potopite v kodo.

Kaj boste zgradili
- Naložiti JSON objekt na IPFS in dobiti nazaj identifikator vsebine (CID).
- Naložiti binarno sliko z diska.
- Pripeti opise in poljubne metapodatke nalaganjem.
- Poizvedovati zgodovino nalaganj po datumskem obsegu.
- Pridobiti podrobnosti določene datoteke.
- Ustvariti časovno omejene podpisane žetone, da lahko brskalnik naloži neposredno, ne da bi izpostavil vaš API ključ.
- Obravnavati napake in implementirati logiko ponovnih poskusov.
Vse teče proti enemu osnovnemu URL-ju: https://api.ipfs.ninja
1. Nastavitev — Registracija in pridobitev API ključa
- Registrirajte se za brezplačen račun (kreditna kartica ni potrebna).
- Pojdite na API Keys v stranski vrstici nadzorne plošče.
- Kliknite Create key, mu dajte ime in takoj kopirajte ključ — ne bo se prikazal znova.

Vaš ključ izgleda tako: bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6. Vsak primer spodaj ga pošlje v glavi X-Api-Key.
2. Nalaganje JSON na IPFS
Najpreprostejše nalaganje: posredujte preprost JavaScript objekt kot content in API ga serializira, pripne na IPFS in vrne CID.
// upload-json.mjs
const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";
const payload = {
content: {
name: "Galactic Badge #42",
description: "Proof of attendance — Galactic Meetup 2026",
attributes: [
{ trait_type: "Event", value: "Galactic Meetup" },
{ trait_type: "Year", value: 2026 }
]
}
};
const res = await fetch(`${API}/upload/new`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": API_KEY
},
body: JSON.stringify(payload)
});
const data = await res.json();
console.log("CID :", data.cid);
console.log("Size:", data.sizeMB, "MB");
console.log("IPFS:", data.uris.ipfs);
console.log("URL :", data.uris.url);Zaženite z node upload-json.mjs. Uspešen odgovor izgleda takole:
{
"cid": "bafkreigx7gq...",
"sizeMB": 0.0004,
"uris": {
"ipfs": "ipfs://bafkreigx7gq...",
"url": "https://ipfs.ninja/ipfs/bafkreigx7gq..."
}
}Polje url kaže na javni HTTP prehod, tako da je vsebina takoj dostopna v katerem koli brskalniku.
3. Nalaganje slike
Binarne datoteke (slike, PDF-ji, zvok) so poslane kot base64-kodirani nizi v polju content.
// upload-image.mjs
import { readFileSync } from "node:fs";
const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";
const imageBuffer = readFileSync("./photo.png");
const base64 = imageBuffer.toString("base64");
const res = await fetch(`${API}/upload/new`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": API_KEY
},
body: JSON.stringify({ content: base64 })
});
const data = await res.json();
console.log("Image CID:", data.cid);
console.log("Gateway :", data.uris.url);API samodejno zazna MIME tip — PNG, JPEG, WebP, GIF in PDF so vsi podprti. Dodatne glave ali preglasi content-type niso potrebni.
S curl-om enaka operacija izgleda takole:
BASE64=$(base64 -w 0 photo.png)
curl -X POST https://api.ipfs.ninja/upload/new \
-H "Content-Type: application/json" \
-H "X-Api-Key: bws_your_key_here" \
-d "{\"content\": \"$BASE64\"}"4. Nalaganje z metapodatki
Vsako nalaganje sprejme dve neobvezni polji: description (oznaka prostega besedila) in metadata (poljubni pari ključ-vrednost). Oba sta shranjena ob CID-u in vrnjena, ko datoteko pozneje izpišete ali pridobite.
// upload-with-metadata.mjs
const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";
const res = await fetch(`${API}/upload/new`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": API_KEY
},
body: JSON.stringify({
content: { title: "Meeting Notes", body: "Q1 roadmap recap..." },
description: "Q1 2026 planning meeting notes",
metadata: {
project: "acme-app",
author: "dana",
version: "1"
}
})
});
const data = await res.json();
console.log("CID:", data.cid);Metapodatki olajšajo filtriranje in organizacijo datotek na vaši strani brez razčlenjevanja same IPFS vsebine.
5. Pripnitev obstoječega CID-a
Če že imate vsebino na IPFS-u in želite zagotoviti, da ostane na voljo, jo pripnite po CID-u:
// pin-cid.mjs
const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";
const res = await fetch(`${API}/pin`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": API_KEY
},
body: JSON.stringify({
cid: "bafkreigx7gq...",
description: "Pinned from external source"
})
});
const data = await res.json();
console.log("Pinned:", data.cid);6. Izpis vaših datotek
Pridobite vsako datoteko, ki ste jo naložili znotraj časovnega okna. Parametra poizvedbe from in to sta Unix časovni žigi v milisekundah.
// list-files.mjs
const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";
const now = Date.now();
const oneWeekAgo = now - 7 * 24 * 60 * 60 * 1000;
const url = `${API}/upload/list?from=${oneWeekAgo}&to=${now}`;
const res = await fetch(url, {
headers: { "X-Api-Key": API_KEY }
});
const files = await res.json();
for (const file of files) {
console.log(`${file.cid} ${file.description ?? "(no description)"}`);
}S curl-om:
FROM=$(($(date +%s) * 1000 - 604800000))
TO=$(($(date +%s) * 1000))
curl -s "https://api.ipfs.ninja/upload/list?from=$FROM&to=$TO" \
-H "X-Api-Key: bws_your_key_here" | jq .7. Podrobnosti datoteke
Pridobite popoln zapis za en CID, vključno z metapodatki, velikostjo in časovnimi žigi:
// get-file.mjs
const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";
const CID = "bafkreigx7gq...";
const res = await fetch(`${API}/file/${CID}`, {
headers: { "X-Api-Key": API_KEY }
});
const details = await res.json();
console.log(JSON.stringify(details, null, 2));8. Nalaganja s strani odjemalca s podpisanimi žetoni
Vdelava API ključa v paket brskalnika predstavlja varnostno tveganje. Namesto tega na svojem strežniku generirajte kratkotrajen podpisan žeton in ga posredujte odjemalcu.
Strežnik (Express)
// server.mjs
import express from "express";
const app = express();
const API = "https://api.ipfs.ninja";
const API_KEY = process.env.IPFS_API_KEY;
app.post("/api/upload-token", async (req, res) => {
const response = await fetch(`${API}/upload/signed-url`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": API_KEY
},
body: JSON.stringify({
name: "browser-upload",
expiresIn: 600 // token valid for 10 minutes
})
});
const { token, tokenId, expiresAt } = await response.json();
res.json({ token, tokenId, expiresAt });
});
app.listen(3000, () => console.log("Server running on :3000"));Odjemalec v brskalniku
<!-- upload.html -->
<input type="file" id="filePicker" />
<button id="uploadBtn">Upload to IPFS</button>
<pre id="result"></pre>
<script>
const API = "https://api.ipfs.ninja";
document.getElementById("uploadBtn").addEventListener("click", async () => {
// 1. Get a signed token from your own backend
const tokenRes = await fetch("/api/upload-token", { method: "POST" });
const { token } = await tokenRes.json();
// 2. Read the selected file as base64
const file = document.getElementById("filePicker").files[0];
if (!file) return alert("Pick a file first");
const base64 = await new Promise((resolve) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result.split(",")[1]);
reader.readAsDataURL(file);
});
// 3. Upload directly to IPFS using the signed token
const uploadRes = await fetch(`${API}/upload/new`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Signed ${token}`
},
body: JSON.stringify({
content: base64,
description: file.name
})
});
const data = await uploadRes.json();
document.getElementById("result").textContent = JSON.stringify(data, null, 2);
});
</script>Brskalnik nikoli ne vidi vašega API ključa. Podpisan žeton samodejno poteče. Žetoni so večkrat uporabni — uporabljati jih je mogoče večkrat, dokler ne potečejo ali so preklicani. useCount se beleži, vendar se ne uveljavlja kot omejitev.
9. Obravnava napak
API uporablja konvencionalne HTTP statusne kode. Tukaj so tisti, ki jih morate eksplicitno obravnavati:
| Status | Pomen | Kaj storiti |
|---|---|---|
| 400 | Bad request — manjkajoča ali neveljavna polja | Preverite, da je content prisoten in veljaven |
| 401 | Unauthorized — napačen ali manjkajoč API ključ | Preverite glavo X-Api-Key |
| 413 | Payload too large | Zmanjšajte velikost datoteke ali razdelite vsebino |
| 429 | Rate limited | Počakajte in poskusite znova z eksponentno zakasnitvijo |
| 500 | Server error | Poskusite znova po kratki zakasnitvi |
Odporna funkcija nalaganja z eksponentnim backoff:
// resilient-upload.mjs
const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";
async function uploadWithRetry(content, retries = 3) {
for (let attempt = 1; attempt <= retries; attempt++) {
const res = await fetch(`${API}/upload/new`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Api-Key": API_KEY
},
body: JSON.stringify({ content })
});
if (res.ok) return await res.json();
const body = await res.text();
if (res.status === 401) {
throw new Error(`Authentication failed: ${body}`);
}
if (res.status === 413) {
throw new Error(`Payload too large — reduce file size. ${body}`);
}
if (res.status === 429 || res.status >= 500) {
const delay = Math.pow(2, attempt) * 1000; // 2s, 4s, 8s
console.warn(`Attempt ${attempt} failed (${res.status}). Retrying in ${delay}ms...`);
await new Promise((r) => setTimeout(r, delay));
continue;
}
throw new Error(`Upload failed (${res.status}): ${body}`);
}
throw new Error("Upload failed after all retries");
}
// Usage
const data = await uploadWithRetry({ hello: "world" });
console.log("CID:", data.cid);10. Popoln delujoč primer
Ena sama skripta, ki uporablja vsako končno točko, pokrito v tem vodiču. Shranite jo kot ipfs-demo.mjs in zaženite z node ipfs-demo.mjs.
// ipfs-demo.mjs
import { readFileSync } from "node:fs";
const API = "https://api.ipfs.ninja";
const API_KEY = "bws_your_key_here";
const headers = {
"Content-Type": "application/json",
"X-Api-Key": API_KEY
};
async function request(method, path, body) {
const opts = { method, headers };
if (body) opts.body = JSON.stringify(body);
const res = await fetch(`${API}${path}`, opts);
if (!res.ok) throw new Error(`${method} ${path} → ${res.status}: ${await res.text()}`);
return res.json();
}
// --- 1. Upload JSON ---
console.log("--- Upload JSON ---");
const jsonResult = await request("POST", "/upload/new", {
content: { name: "Demo Token", edition: 1 },
description: "Tutorial demo — JSON upload",
metadata: { tutorial: "true" }
});
console.log("CID:", jsonResult.cid);
console.log("URL:", jsonResult.uris.url);
// --- 2. Upload an image (if photo.png exists) ---
try {
const img = readFileSync("./photo.png");
console.log("\n--- Upload Image ---");
const imgResult = await request("POST", "/upload/new", {
content: img.toString("base64"),
description: "Tutorial demo — image upload"
});
console.log("CID:", imgResult.cid);
console.log("URL:", imgResult.uris.url);
} catch {
console.log("\n--- Skipping image upload (no photo.png found) ---");
}
// --- 3. Pin the JSON CID ---
console.log("\n--- Pin CID ---");
const pinResult = await request("POST", "/pin", {
cid: jsonResult.cid,
description: "Pinned from tutorial"
});
console.log("Pinned:", pinResult.cid);
// --- 4. Get file details ---
console.log("\n--- File Details ---");
const details = await request("GET", `/file/${jsonResult.cid}`);
console.log(JSON.stringify(details, null, 2));
// --- 5. List recent files ---
console.log("\n--- Recent Files ---");
const now = Date.now();
const oneHourAgo = now - 60 * 60 * 1000;
const files = await request("GET", `/upload/list?from=${oneHourAgo}&to=${now}`);
console.log(`Found ${files.length} file(s) in the last hour`);
for (const f of files) {
console.log(` - ${f.cid} ${f.description ?? ""}`);
}
// --- 6. Create a signed upload token ---
console.log("\n--- Signed Token ---");
const tokenResult = await request("POST", "/upload/signed-url", {
name: "demo-token",
expiresIn: 300
});
console.log("Token ID :", tokenResult.tokenId);
console.log("Expires :", new Date(tokenResult.expiresAt).toISOString());
// --- 7. Upload using the signed token ---
console.log("\n--- Upload with Signed Token ---");
const signedRes = await fetch(`${API}/upload/new`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Signed ${tokenResult.token}`
},
body: JSON.stringify({
content: { note: "Uploaded with a signed token" }
})
});
const signedData = await signedRes.json();
console.log("CID:", signedData.cid);
console.log("\nDone.");Zamenjajte bws_your_key_here z resničnim ključem in zaženite skripto. Vsak korak natisne svoj rezultat, da lahko sledite.
11. Naslednji koraki
Zdaj veste, kako nalagati, pripenjati, izpisovati in pridobivati datoteke prek IPFS Upload API in kako ohranjati varna nalaganja v brskalniku s podpisanimi žetoni. Za širši pregled, vključno z UI nadzorne plošče in primeri Python, glejte Kako naložiti datoteke na IPFS. Kam iti od tukaj:
- API Reference — Popolna dokumentacija končnih točk na ipfs.ninja/docs.
- Prilagojeni prehodi — Postrezite vsebino IPFS s svoje lastne domene. Glejte vodič za nastavitev prehoda.
- Analitika — Spremljajte obseg nalaganj, pasovno širino in število pripenjanj v nadzorni plošči.
- HTTP odjemalec — SDK ni potreben. Za interakcijo z API-jem lahko uporabite standardni
fetch()ali katerega koli HTTP odjemalca.
Če naletite na težave, odprite tiket na support.ipfs.ninja ali se pridružite skupnosti na Discordu.
