· Nacho Coll · Tutorials · 9 min läsning
IPFS Upload API — Komplett utvecklarhandledning
Lär dig att ladda upp filer till IPFS via REST API. Fullständiga kodexempel i JavaScript, Node.js och curl. Ladda upp JSON, bilder, använd signerade tokens för uppladdningar på klientsidan.

IPFS Upload API — Komplett utvecklarhandledning
Att ladda upp filer till IPFS borde vara så enkelt som att göra en POST-begäran. I denna handledning kommer du att göra precis det — ladda upp JSON-dokument, bilder och PDF-filer till IPFS med inget mer än fetch() och en API-nyckel. I slutet kommer du ha ett komplett Node.js-skript som laddar upp innehåll, listar filer, hämtar metadata och genererar signerade tokens för säkra uppladdningar på klientsidan. Ny på IPFS? Börja med Vad är IPFS Pinning? för att förstå grunderna innan du dyker in i koden.

Vad du kommer att bygga
- Ladda upp ett JSON-objekt till IPFS och få tillbaka en innehållsidentifierare (CID).
- Ladda upp en binär bild från disk.
- Bifoga beskrivningar och anpassad metadata till uppladdningar.
- Fråga din uppladdningshistorik efter datumintervall.
- Hämta detaljer för en specifik fil.
- Skapa tidsbegränsade signerade tokens så att en webbläsare kan ladda upp direkt utan att exponera din API-nyckel.
- Hantera fel och implementera retry-logik.
Allt körs mot en enda bas-URL: https://api.ipfs.ninja
1. Inställning — Registrera dig och få en API-nyckel
- Registrera dig för ett gratis konto (inget kreditkort krävs).
- Gå till API Keys i dashboard-sidofältet.
- Klicka på Create key, ge det ett namn och kopiera nyckeln omedelbart — den kommer inte att visas igen.

Din nyckel ser ut som bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6. Varje exempel nedan skickar den i X-Api-Key-headern.
2. Ladda upp JSON till IPFS
Den enklaste uppladdningen: skicka ett vanligt JavaScript-objekt som content och API:et serialiserar det, pinnar det till IPFS och returnerar 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);Kör med node upload-json.mjs. Ett lyckat svar ser ut så här:
{
"cid": "bafkreigx7gq...",
"sizeMB": 0.0004,
"uris": {
"ipfs": "ipfs://bafkreigx7gq...",
"url": "https://ipfs.ninja/ipfs/bafkreigx7gq..."
}
}url-fältet pekar på en publik HTTP-gateway, så innehållet är omedelbart tillgängligt i vilken webbläsare som helst.
3. Ladda upp en bild
Binära filer (bilder, PDF-filer, ljud) skickas som base64-kodade strängar i content-fältet.
// 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:et upptäcker MIME-typen automatiskt — PNG, JPEG, WebP, GIF och PDF stöds alla. Inga extra headers eller content-type-överskridningar krävs.
Med curl ser samma operation ut så här:
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. Uppladdning med metadata
Varje uppladdning accepterar två valfria fält: description (fri textetikett) och metadata (godtyckliga nyckel-värde-par). Båda lagras tillsammans med CID:n och returneras när du listar eller hämtar filen senare.
// 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);Metadata gör det enkelt att filtrera och organisera filer på din sida utan att parsea IPFS-innehållet självt.
5. Pinna en befintlig CID
Om du redan har innehåll på IPFS och vill säkerställa att det förblir tillgängligt, pinna det med CID:
// 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. Lista dina filer
Hämta varje fil du har laddat upp inom ett tidsfönster. Frågeparametrarna from och to är Unix-tidsstämplar i millisekunder.
// 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)"}`);
}Med curl:
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. Få fildetaljer
Hämta hela posten för en enskild CID, inklusive metadata, storlek och tidsstämplar:
// 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. Uppladdningar på klientsidan med signerade tokens
Att bädda in en API-nyckel i ett webbläsarpaket är en säkerhetsrisk. Generera istället en kortlivad signerad token på din server och skicka den till klienten.
Server (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"));Webbläsarklient
<!-- 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>Webbläsaren ser aldrig din API-nyckel. Den signerade token löper ut automatiskt. Tokens är fleranvändbara — de kan användas flera gånger tills de löper ut eller återkallas. useCount spåras men tillämpas inte som en gräns.
9. Felhantering
API:et använder konventionella HTTP-statuskoder. Här är de som du bör hantera explicit:
| Status | Betydelse | Vad göra |
|---|---|---|
| 400 | Bad request — saknade eller ogiltiga fält | Kontrollera att content finns och är giltigt |
| 401 | Unauthorized — dålig eller saknad API-nyckel | Verifiera X-Api-Key-headern |
| 413 | Payload för stor | Minska filstorlek eller dela upp innehållet |
| 429 | Hastighetsbegränsad | Backa av och försök igen med exponentiell fördröjning |
| 500 | Serverfel | Försök igen efter en kort fördröjning |
En motståndskraftig uppladdningsfunktion med exponentiell 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. Komplett arbetsexempel
Ett enda skript som tränar varje endpoint som täcks i denna handledning. Spara det som ipfs-demo.mjs och kör med 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.");Ersätt bws_your_key_here med en riktig nyckel och kör skriptet. Varje steg skriver ut sitt resultat så att du kan följa med.
11. Nästa steg
Du vet nu hur du laddar upp, pinnar, listar och hämtar filer via IPFS Upload API och hur du håller webbläsaruppladdningar säkra med signerade tokens. För en bredare översikt inklusive dashboard-UI och Python-exempel, se Hur man laddar upp filer till IPFS. Här är vart du går härifrån:
- API-referens — Fullständig endpoint-dokumentation på ipfs.ninja/docs.
- Anpassade gateways — Servera IPFS-innehåll från din egen domän. Se gateway-inställningsguide.
- Analyser — Spåra uppladdningsvolym, bandbredd och pin-antal i dashboarden.
- HTTP-klient — Inget SDK krävs. Du kan använda standard
fetch()eller vilken HTTP-klient som helst för att interagera med API:et.
Om du stöter på problem, öppna en biljett på support.ipfs.ninja eller gå med i communityn på Discord.
