· Nacho Coll · Tutorials  · 9 min læsning

IPFS Upload API — Komplet udviklertutorial

Lær at uploade filer til IPFS via REST API. Komplette kodeeksempler i JavaScript, Node.js og curl. Upload JSON, billeder, brug signerede tokens til client-side uploads.

Lær at uploade filer til IPFS via REST API. Komplette kodeeksempler i JavaScript, Node.js og curl. Upload JSON, billeder, brug signerede tokens til client-side uploads.

IPFS Upload API — Komplet udviklertutorial

At uploade filer til IPFS bør være lige så simpelt som at lave en POST-anmodning. I denne tutorial vil du gøre præcis det — uploade JSON-dokumenter, billeder og PDF’er til IPFS med intet mere end fetch() og en API-nøgle. Til sidst vil du have et komplet Node.js-script, der uploader indhold, lister filer, henter metadata og genererer signerede tokens til sikre client-side uploads. Ny til IPFS? Start med Hvad er IPFS Pinning? for at forstå grundlæggende, før du dykker ind i koden.

IPFS Ninja API keys management page

Hvad du vil bygge

  • Upload et JSON-objekt til IPFS og få tilbage en indholdsidentifikator (CID).
  • Upload et binært billede fra disken.
  • Vedhæft beskrivelser og brugerdefineret metadata til uploads.
  • Forespørg din uploadhistorik efter datointerval.
  • Hent detaljer for en specifik fil.
  • Opret tidsbegrænsede signerede tokens, så en browser kan uploade direkte uden at eksponere din API-nøgle.
  • Håndter fejl og implementer retry-logik.

Alt kører mod en enkelt base-URL: https://api.ipfs.ninja

1. Opsætning — Tilmeld dig og få en API-nøgle

  1. Tilmeld dig en gratis konto (intet kreditkort kræves).
  2. Gå til API Keys i dashboardets sidepanel.
  3. Klik på Create key, giv den et navn, og kopier nøglen med det samme — den vil ikke blive vist igen.
API Keys page — create and manage your keys

Din nøgle ser ud som bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6. Hvert eksempel nedenfor sender den i X-Api-Key-headeren.

2. Upload JSON til IPFS

Den simpleste upload: send et almindeligt 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);

Kør med node upload-json.mjs. Et succesfuldt svar ser ud sådan her:

{
  "cid": "bafkreigx7gq...",
  "sizeMB": 0.0004,
  "uris": {
    "ipfs": "ipfs://bafkreigx7gq...",
    "url": "https://ipfs.ninja/ipfs/bafkreigx7gq..."
  }
}

url-feltet peger på en offentlig HTTP-gateway, så indholdet er straks tilgængeligt i enhver browser.

3. Upload et billede

Binære filer (billeder, PDF’er, lyd) sendes som base64-kodede strenge 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 registrerer MIME-typen automatisk — PNG, JPEG, WebP, GIF og PDF er alle understøttede. Ingen ekstra headers eller content-type overrides er påkrævet.

Med curl ser den samme operation sådan ud:

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. Upload med metadata

Hver upload accepterer to valgfrie felter: description (fri tekstetiket) og metadata (vilkårlige nøgle-værdi-par). Begge gemmes ved siden af 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 gør det nemt at filtrere og organisere filer på din side uden at parse IPFS-indholdet selv.

5. Pin en eksisterende CID

Hvis du allerede har indhold på IPFS og vil sikre, at det forbliver tilgængeligt, 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 dine filer

Hent hver fil, du har uploadet inden for et tidsvindue. Forespørgselsparametrene 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 fulde post for en enkelt CID, inklusive 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. Client-side uploads med signerede tokens

At indlejre en API-nøgle i et browserbundt er en sikkerhedsrisiko. Generér i stedet et kortlivet signeret token på din server 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"));

Browser-klient

<!-- 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>

Browseren ser aldrig din API-nøgle. Det signerede token udløber automatisk. Tokens er fler-brugs — de kan bruges flere gange, indtil de udløber eller tilbagekaldes. useCount spores, men håndhæves ikke som en grænse.

9. Fejlhåndtering

API’en bruger konventionelle HTTP-statuskoder. Her er dem, du bør håndtere eksplicit:

StatusBetydningHvad gøre
400Bad request — manglende eller ugyldige felterKontroller, at content er til stede og gyldigt
401Unauthorized — dårlig eller manglende API-nøgleVerificer X-Api-Key-headeren
413Payload for storReducer filstørrelse eller del indholdet
429HastighedsbegrænsetTræk dig tilbage og prøv igen med eksponentiel forsinkelse
500ServerfejlPrøv igen efter en kort forsinkelse

En modstandsdygtig uploadfunktion med eksponentiel 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. Komplet arbejdseksempel

Et enkelt script, der træner hver endpoint, der dækkes i denne tutorial. Gem det som ipfs-demo.mjs og 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.");

Erstat bws_your_key_here med en rigtig nøgle og kør scriptet. Hvert trin udskriver sit resultat, så du kan følge med.

11. Næste skridt

Du ved nu, hvordan du uploader, pinner, lister og henter filer gennem IPFS Upload API, og hvordan du holder browser-uploads sikre med signerede tokens. For et bredere overblik inklusive dashboard-UI og Python-eksempler, se Sådan uploader du filer til IPFS. Her er, hvor du kan gå herfra:

  • API-reference — Komplet endpoint-dokumentation på ipfs.ninja/docs.
  • Tilpassede gateways — Server IPFS-indhold fra dit eget domæne. Se gateway-opsætningsguide.
  • Analyse — Spor uploadvolumen, båndbredde og pin-antal i dashboardet.
  • HTTP-klient — Ingen SDK påkrævet. Du kan bruge standard fetch() eller enhver HTTP-klient til at interagere med API’en.

Hvis du støder på problemer, åbn en billet på support.ipfs.ninja eller gå med i community’et på Discord.

Tilbage til Bloggen

Relaterede artikler

Se alle artikler »