· Nacho Coll · Tutorials  · 10 λεπτά ανάγνωσης

IPFS Upload API — Πλήρης οδηγός για προγραμματιστές

Μάθετε να ανεβάζετε αρχεία στο IPFS μέσω REST API. Πλήρη παραδείγματα κώδικα σε JavaScript, Node.js και curl. Ανεβάστε JSON, εικόνες, χρησιμοποιήστε υπογεγραμμένα tokens για uploads από τον client.

Μάθετε να ανεβάζετε αρχεία στο IPFS μέσω REST API. Πλήρη παραδείγματα κώδικα σε JavaScript, Node.js και curl. Ανεβάστε JSON, εικόνες, χρησιμοποιήστε υπογεγραμμένα tokens για uploads από τον client.

IPFS Upload API — Πλήρης οδηγός για προγραμματιστές

Η μεταφόρτωση αρχείων στο IPFS θα έπρεπε να είναι τόσο απλή όσο η αποστολή ενός POST αιτήματος. Σε αυτόν τον οδηγό θα κάνετε ακριβώς αυτό — θα ανεβάσετε JSON έγγραφα, εικόνες και PDF στο IPFS με τίποτα περισσότερο από fetch() και ένα API key. Στο τέλος θα έχετε ένα πλήρες Node.js script που ανεβάζει περιεχόμενο, παραθέτει αρχεία, ανακτά metadata και δημιουργεί υπογεγραμμένα tokens για ασφαλή uploads από τον client. Νέος στο IPFS; Ξεκινήστε με το Τι είναι το IPFS Pinning; για να κατανοήσετε τα βασικά πριν βουτήξετε στον κώδικα.

IPFS Ninja API keys management page

Τι θα φτιάξετε

  • Ανεβάστε ένα JSON αντικείμενο στο IPFS και πάρτε πίσω ένα content identifier (CID).
  • Ανεβάστε μια δυαδική εικόνα από τον δίσκο.
  • Επισυνάψτε περιγραφές και προσαρμοσμένα metadata στα uploads.
  • Αναζητήστε το ιστορικό uploads σας ανά εύρος ημερομηνιών.
  • Ανακτήστε λεπτομέρειες για ένα συγκεκριμένο αρχείο.
  • Δημιουργήστε χρονικά περιορισμένα υπογεγραμμένα tokens ώστε ένας browser να μπορεί να ανεβάζει απευθείας χωρίς να εκθέτει το API key σας.
  • Διαχειριστείτε σφάλματα και υλοποιήστε λογική επανάληψης.

Τα πάντα τρέχουν σε μία βασική URL: https://api.ipfs.ninja

1. Setup — Εγγραφή και απόκτηση API key

  1. Εγγραφείτε για δωρεάν λογαριασμό (δεν απαιτείται πιστωτική κάρτα).
  2. Πηγαίνετε στο API Keys στην πλαϊνή μπάρα του dashboard.
  3. Κάντε κλικ στο Create key, δώστε του ένα όνομα και αντιγράψτε το κλειδί αμέσως — δεν θα εμφανιστεί ξανά.
API Keys page — create and manage your keys

Το κλειδί σας μοιάζει με bws_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6. Κάθε παρακάτω παράδειγμα το στέλνει στην κεφαλίδα X-Api-Key.

2. Ανέβασμα JSON στο IPFS

Το απλούστερο upload: περάστε ένα απλό JavaScript αντικείμενο ως content και το API το serializei, το pinari στο IPFS και επιστρέφει το 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);

Τρέξτε με node upload-json.mjs. Μια επιτυχημένη απάντηση μοιάζει έτσι:

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

Το πεδίο url δείχνει σε μια δημόσια HTTP πύλη, οπότε το περιεχόμενο είναι άμεσα προσβάσιμο σε οποιονδήποτε browser.

3. Ανέβασμα εικόνας

Τα δυαδικά αρχεία (εικόνες, PDF, ήχος) στέλνονται ως base64-encoded strings στο πεδίο 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 εντοπίζει αυτόματα τον τύπο MIME — PNG, JPEG, WebP, GIF και PDF υποστηρίζονται όλα. Δεν χρειάζονται επιπλέον κεφαλίδες ή content-type overrides.

Με curl η ίδια λειτουργία μοιάζει έτσι:

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 με metadata

Κάθε upload δέχεται δύο προαιρετικά πεδία: description (ελεύθερη ετικέτα κειμένου) και metadata (αυθαίρετα ζεύγη κλειδιού-τιμής). Και τα δύο αποθηκεύονται μαζί με το CID και επιστρέφονται όταν παραθέτετε ή ανακτάτε το αρχείο αργότερα.

// 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 διευκολύνουν το φιλτράρισμα και την οργάνωση αρχείων από την πλευρά σας χωρίς να αναλύετε το ίδιο το περιεχόμενο IPFS.

5. Pin σε υπάρχον CID

Αν έχετε ήδη περιεχόμενο στο IPFS και θέλετε να βεβαιωθείτε ότι παραμένει διαθέσιμο, κάντε pin βάσει 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. Παράθεση των αρχείων σας

Ανακτήστε κάθε αρχείο που έχετε ανεβάσει σε ένα χρονικό παράθυρο. Τα query parameters from και to είναι Unix timestamps σε milliseconds.

// 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)"}`);
}

Με 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. Λεπτομέρειες αρχείου

Ανακτήστε την πλήρη εγγραφή για ένα CID, συμπεριλαμβανομένων metadata, μεγέθους και timestamps:

// 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. Uploads από Client με υπογεγραμμένα tokens

Η ενσωμάτωση ενός API key σε ένα bundle browser είναι κίνδυνος ασφαλείας. Αντ’ αυτού, δημιουργήστε ένα βραχείας διάρκειας υπογεγραμμένο token στον server σας και περάστε το στον client.

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"));

Client Browser

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

Ο browser δεν βλέπει ποτέ το API key σας. Το υπογεγραμμένο token λήγει αυτόματα. Τα tokens είναι πολλαπλής χρήσης — μπορούν να χρησιμοποιηθούν πολλές φορές μέχρι να λήξουν ή να ανακληθούν. Ο useCount παρακολουθείται αλλά δεν επιβάλλεται ως όριο.

9. Διαχείριση σφαλμάτων

Το API χρησιμοποιεί συμβατικούς κωδικούς κατάστασης HTTP. Εδώ είναι αυτοί που πρέπει να διαχειριστείτε ρητά:

StatusΣημασίαΤι να κάνετε
400Bad request — πεδία που λείπουν ή είναι μη έγκυραΕλέγξτε ότι το content υπάρχει και είναι έγκυρο
401Unauthorized — λάθος ή ελλιπές API keyΕπαληθεύστε την κεφαλίδα X-Api-Key
413Payload too largeΜειώστε το μέγεθος αρχείου ή χωρίστε το περιεχόμενο
429Rate limitedΚάντε back off και προσπαθήστε ξανά με εκθετική καθυστέρηση
500Server errorΠροσπαθήστε ξανά μετά από σύντομη καθυστέρηση

Μια ανθεκτική συνάρτηση upload με εκθετικό 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. Πλήρες παράδειγμα εργασίας

Ένα μόνο script που ασκεί κάθε endpoint που καλύπτεται σε αυτόν τον οδηγό. Αποθηκεύστε το ως ipfs-demo.mjs και τρέξτε με 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.");

Αντικαταστήστε το bws_your_key_here με ένα πραγματικό κλειδί και τρέξτε το script. Κάθε βήμα τυπώνει το αποτέλεσμά του ώστε να μπορείτε να το παρακολουθήσετε.

11. Επόμενα βήματα

Τώρα ξέρετε πώς να ανεβάζετε, να κάνετε pin, να παραθέτετε και να ανακτάτε αρχεία μέσω του IPFS Upload API και πώς να διατηρείτε τα browser uploads ασφαλή με υπογεγραμμένα tokens. Για μια ευρύτερη επισκόπηση που περιλαμβάνει το UI του dashboard και παραδείγματα Python, δείτε το Πώς να ανεβάσετε αρχεία στο IPFS. Εδώ είναι πού να πάτε από εδώ και πέρα:

  • API Reference — Πλήρης τεκμηρίωση endpoint στο ipfs.ninja/docs.
  • Custom Gateways — Σερβίρετε περιεχόμενο IPFS από το δικό σας domain. Δείτε τον οδηγό ρύθμισης gateway.
  • Analytics — Παρακολουθήστε όγκο upload, bandwidth και αριθμό pin στο dashboard.
  • HTTP Client — Δεν απαιτείται SDK. Μπορείτε να χρησιμοποιήσετε τυπικό fetch() ή οποιονδήποτε HTTP client για να αλληλεπιδράσετε με το API.

Αν συναντήσετε προβλήματα, ανοίξτε ένα ticket στο support.ipfs.ninja ή ενταχθείτε στην κοινότητα στο Discord.

Πίσω στο Blog

Σχετικά Άρθρα

Δείτε Όλα τα Άρθρα »