· Nacho Coll · Tutorials · 9 min lesing
IPFS Upload API — Komplett utvikleropplæring
Lær å laste opp filer til IPFS via REST API. Komplette kodeeksempler i JavaScript, Node.js og curl. Last opp JSON, bilder, bruk signerte tokens for klientsideopplastinger.

IPFS Upload API — Komplett utvikleropplæring
Å laste opp filer til IPFS bør være like enkelt som å lage en POST-forespørsel. I denne opplæringen gjør du nettopp det — laster opp JSON-dokumenter, bilder og PDF-er til IPFS med ingenting mer enn fetch() og en API-nøkkel. Til slutt vil du ha et komplett Node.js-skript som laster opp innhold, lister filer, henter metadata, og genererer signerte tokens for sikre klientsideopplastinger. Ny på IPFS? Start med Hva er IPFS Pinning? for å forstå grunnleggende før du dykker inn i koden.

Hva du vil bygge
- Last opp et JSON-objekt til IPFS og få tilbake en innholdsidentifikator (CID).
- Last opp et binært bilde fra disk.
- Legg ved beskrivelser og tilpasset metadata til opplastinger.
- Spør etter opplastingshistorikken din etter datointervall.
- Hent detaljer for en spesifikk fil.
- Opprett tidsbegrensede signerte tokens slik at en nettleser kan laste opp direkte uten å avsløre API-nøkkelen din.
- Håndter feil og implementer retry-logikk.
Alt kjører mot en enkelt base-URL: https://api.ipfs.ninja
1. Oppsett — Registrer deg og få en API-nøkkel
- Registrer deg for en gratis konto (ingen kredittkort kreves).
- Gå til API Keys i dashbordets sidefelt.
- Klikk Create key, gi den et navn, og kopier nøkkelen umiddelbart — den vises ikke igjen.

Nøkkelen din ser ut som bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6. Hvert eksempel nedenfor sender den i X-Api-Key-headeren.
2. Last opp JSON til IPFS
Den enkleste opplastingen: send et vanlig JavaScript-objekt som content, og API-en serialiserer det, pinner det til IPFS, og returnerer CID-en.
// 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);Kjør med node upload-json.mjs. Et vellykket svar ser slik ut:
{
"cid": "bafkreigx7gq...",
"sizeMB": 0.0004,
"uris": {
"ipfs": "ipfs://bafkreigx7gq...",
"url": "https://ipfs.ninja/ipfs/bafkreigx7gq..."
}
}url-feltet peker på en offentlig HTTP-gateway, så innholdet er umiddelbart tilgjengelig i enhver nettleser.
3. Last opp et bilde
Binære filer (bilder, PDF-er, lyd) sendes som base64-kodede strenger i content-feltet.
// 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-en oppdager MIME-typen automatisk — PNG, JPEG, WebP, GIF og PDF støttes alle. Ingen ekstra headere eller content-type-overstyringer kreves.
Med curl ser den samme operasjonen slik ut:
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. Opplasting med metadata
Hver opplasting godtar to valgfrie felt: description (fri tekstetikett) og metadata (vilkårlige nøkkel-verdi-par). Begge lagres sammen med CID-en og returneres når du senere lister eller henter filen.
// 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 gjør det enkelt å filtrere og organisere filer på din side uten å parse IPFS-innholdet selv.
5. Pin en eksisterende CID
Hvis du allerede har innhold på IPFS og vil sikre at det forblir tilgjengelig, pin 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. List filene dine
Hent hver fil du har lastet opp innen et tidsvindu. Spørringsparametrene from og to er Unix-tidsstempler 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. Hent fildetaljer
Hent den fullstendige posten for en enkelt CID, inkludert metadata, størrelse og tidsstempler:
// 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. Klientsideopplastinger med signerte tokens
Å bygge inn en API-nøkkel i en nettleserpakke er en sikkerhetsrisiko. Generer i stedet et kortvarig signert token på serveren din og send det til 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"));Nettleserklient
<!-- 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>Nettleseren ser aldri API-nøkkelen din. Det signerte tokenet utløper automatisk. Tokens er flerbruk — de kan brukes flere ganger til de utløper eller blir tilbakekalt. useCount spores, men håndheves ikke som en grense.
9. Feilhåndtering
API-en bruker konvensjonelle HTTP-statuskoder. Her er de du bør håndtere eksplisitt:
| Status | Betydning | Hva gjøre |
|---|---|---|
| 400 | Bad request — manglende eller ugyldige felt | Sjekk at content er til stede og gyldig |
| 401 | Unauthorized — dårlig eller manglende API-nøkkel | Verifiser X-Api-Key-headeren |
| 413 | Payload for stor | Reduser filstørrelse eller del innholdet |
| 429 | Hastighetsbegrenset | Trekk deg tilbake og prøv igjen med eksponentiell forsinkelse |
| 500 | Serverfeil | Prøv igjen etter en kort forsinkelse |
En motstandsdyktig opplastingsfunksjon med eksponentiell 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 arbeidseksempel
Et enkelt skript som trener hver endepunkt dekket i denne opplæringen. Lagre det som ipfs-demo.mjs og kjø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.");Erstatt bws_your_key_here med en ekte nøkkel og kjør skriptet. Hvert trinn skriver ut resultatet sitt slik at du kan følge med.
11. Neste skritt
Du vet nå hvordan du laster opp, pinner, lister og henter filer gjennom IPFS Upload API og hvordan du holder nettleseropplastinger sikre med signerte tokens. For et bredere overblikk inkludert dashboard-UI og Python-eksempler, se Hvordan laste opp filer til IPFS. Her er hvor du kan dra herfra:
- API-referanse — Komplett endepunktdokumentasjon på ipfs.ninja/docs.
- Tilpassede gateways — Server IPFS-innhold fra ditt eget domene. Se gateway-oppsettsveiledning.
- Analytikk — Spor opplastingsvolum, båndbredde og pin-tellinger i dashbordet.
- HTTP-klient — Ingen SDK påkrevd. Du kan bruke standard
fetch()eller en hvilken som helst HTTP-klient for å interagere med API-en.
Hvis du støter på problemer, åpne en billett på support.ipfs.ninja eller bli med i fellesskapet på Discord.
