Skip to content

Compatibilidad con S3

Usa el AWS SDK para subir, descargar y gestionar archivos en IPFS Ninja con el mismo código que usas para Amazon S3.

Endpoint

https://s3.ipfs.ninja

Credenciales

La API S3 utiliza tu clave API de IPFS Ninja para la autenticación. Tu clave API sirve tanto como access key como secret key.

Cómo obtener tus credenciales

  1. Ve a Dashboard > API Keys
  2. Haz clic en Create API key y asígnale un nombre (por ejemplo, «Acceso S3»)
  3. Copia la clave completa inmediatamente — solo se muestra una vez y no puede recuperarse después

Tu clave tiene este formato:

bws_628bba35e9e0079d9ff9c392b1b55a7b
├──────────┘└──────────────────────────┘
 prefix (12 chars)    rest of key

Correspondencia con credenciales AWS

Parámetro AWSValorEjemplo
accessKeyIdPrimeros 12 caracteres de tu clave APIbws_628bba35
secretAccessKeyLa clave API completa (los 36 caracteres)bws_628bba35e9e0079d9ff9c392b1b55a7b
regionSiempre us-east-1us-east-1

WARNING

La clave API completa solo se muestra una vez al crearla. Si la pierdes, elimina la clave y crea una nueva desde la página de API Keys.

Inicio Rápido

javascript
import { S3Client, PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";

const s3 = new S3Client({
  endpoint: "https://s3.ipfs.ninja",
  credentials: {
    accessKeyId: "bws_628bba35",
    secretAccessKey: "bws_628bba35e9e0079d9ff9c392b1b55a7b"
  },
  region: "us-east-1",
  forcePathStyle: true
});

// Upload a file
const put = await s3.send(new PutObjectCommand({
  Bucket: "my-project",
  Key: "hello.json",
  Body: JSON.stringify({ hello: "IPFS" }),
  ContentType: "application/json"
}));

console.log("CID:", put.Metadata?.cid);
// CID: QmXnnyufdzAWL5CqZ2RnSNgPbvCc1ALT73s6epPrRnZ1Xy

Buckets = Carpetas

Los buckets de S3 corresponden a tus carpetas de IPFS Ninja. Cuando subes un archivo a un bucket, se almacena en la carpeta correspondiente. Cuando listas los objetos de un bucket, ves los archivos de esa carpeta.

Operación S3Equivalente en IPFS Ninja
CreateBucketCrear una nueva carpeta
ListBucketsListar tus carpetas
DeleteBucketEliminar una carpeta y todos sus archivos
PutObject en bucketSubir archivo a la carpeta
ListObjectsV2 en bucketListar archivos en la carpeta
javascript
import { ListBucketsCommand, CreateBucketCommand, PutObjectCommand } from "@aws-sdk/client-s3";

// Create a bucket (= create a folder)
await s3.send(new CreateBucketCommand({ Bucket: "nft-metadata" }));

// Upload a file into the folder
await s3.send(new PutObjectCommand({
  Bucket: "nft-metadata",      // ← folder name
  Key: "token-42.json",        // ← filename within the folder
  Body: JSON.stringify({ name: "My NFT #42" })
}));

// List buckets (= list your folders)
const { Buckets } = await s3.send(new ListBucketsCommand({}));
console.log(Buckets);
// [{ Name: "nft-metadata", CreationDate: "2026-04-13T..." }]

TIP

Las carpetas creadas a través de la API S3 son las mismas carpetas visibles en tu Dashboard. Puedes organizar archivos desde la API S3, la API REST o la interfaz web — todas comparten el mismo sistema de carpetas.

INFO

A diferencia de Amazon S3, las carpetas de IPFS Ninja son planas por defecto. Para crear estructuras anidadas, usa los endpoints de carpetas de la API REST con parentFolderId. Desde la API S3, usa prefijos de clave (por ejemplo, images/photo.png) para organizar dentro de una carpeta.

Operaciones Soportadas

PutObject

Sube un archivo a IPFS. El archivo se pinea, se escanea por seguridad, y el CID se devuelve en los headers ETag y x-amz-meta-cid.

javascript
import { PutObjectCommand } from "@aws-sdk/client-s3";
import fs from "fs";

const result = await s3.send(new PutObjectCommand({
  Bucket: "my-project",
  Key: "photo.png",
  Body: fs.readFileSync("photo.png"),
  ContentType: "image/png"
}));

console.log("CID:", result.ETag);
bash
# curl equivalent
curl -X PUT "https://s3.ipfs.ninja/my-project/photo.png" \
  --data-binary @photo.png \
  -H "Content-Type: image/png" \
  --aws-sigv4 "aws:amz:us-east-1:s3" \
  --user "bws_628bba35:bws_628bba35e9e0079d9ff9c392b1b55a7b"

GetObject

Descarga un archivo por su clave (nombre de archivo) o CID.

javascript
import { GetObjectCommand } from "@aws-sdk/client-s3";

const result = await s3.send(new GetObjectCommand({
  Bucket: "my-project",
  Key: "photo.png"
}));

const body = await result.Body.transformToByteArray();
console.log("Size:", body.length);
console.log("CID:", result.Metadata?.cid);

HeadObject

Obtiene los metadatos de un archivo sin descargar el contenido.

javascript
import { HeadObjectCommand } from "@aws-sdk/client-s3";

const head = await s3.send(new HeadObjectCommand({
  Bucket: "my-project",
  Key: "photo.png"
}));

console.log("Size:", head.ContentLength);
console.log("Type:", head.ContentType);
console.log("CID:", head.Metadata?.cid);

DeleteObject

Elimina el pin de un archivo de IPFS y lo borra de tu cuenta.

javascript
import { DeleteObjectCommand } from "@aws-sdk/client-s3";

await s3.send(new DeleteObjectCommand({
  Bucket: "my-project",
  Key: "photo.png"
}));

ListObjectsV2

Lista los archivos de un bucket con filtrado opcional por prefijo y paginación.

javascript
import { ListObjectsV2Command } from "@aws-sdk/client-s3";

const list = await s3.send(new ListObjectsV2Command({
  Bucket: "my-project",
  Prefix: "images/",
  MaxKeys: 100
}));

for (const obj of list.Contents ?? []) {
  console.log(obj.Key, obj.Size, obj.ETag); // ETag = CID
}

Multipart Upload

Sube archivos grandes (hasta 5 GB) usando multipart upload. El AWS SDK lo gestiona automáticamente:

javascript
import { Upload } from "@aws-sdk/lib-storage";
import fs from "fs";

const upload = new Upload({
  client: s3,
  params: {
    Bucket: "my-project",
    Key: "large-dataset.tar.gz",
    Body: fs.createReadStream("large-dataset.tar.gz"),
    ContentType: "application/gzip"
  },
  partSize: 10 * 1024 * 1024, // 10 MB per part
});

upload.on("httpUploadProgress", (progress) => {
  console.log(`Uploaded ${progress.loaded} of ${progress.total} bytes`);
});

const result = await upload.done();
console.log("CID:", result.ETag);

O controla las partes manualmente:

javascript
import {
  CreateMultipartUploadCommand,
  UploadPartCommand,
  CompleteMultipartUploadCommand
} from "@aws-sdk/client-s3";

// 1. Start
const { UploadId } = await s3.send(new CreateMultipartUploadCommand({
  Bucket: "my-project",
  Key: "big-file.bin"
}));

// 2. Upload parts
const part1 = await s3.send(new UploadPartCommand({
  Bucket: "my-project",
  Key: "big-file.bin",
  UploadId,
  PartNumber: 1,
  Body: chunk1
}));

// 3. Complete
const result = await s3.send(new CompleteMultipartUploadCommand({
  Bucket: "my-project",
  Key: "big-file.bin",
  UploadId,
  MultipartUpload: {
    Parts: [{ PartNumber: 1, ETag: part1.ETag }]
  }
}));

Ejemplo en Python

python
import boto3

s3 = boto3.client(
    "s3",
    endpoint_url="https://s3.ipfs.ninja",
    aws_access_key_id="bws_628bba35",
    aws_secret_access_key="bws_628bba35e9e0079d9ff9c392b1b55a7b",
    region_name="us-east-1"
)

# Upload
s3.put_object(
    Bucket="my-project",
    Key="data.json",
    Body=b'{"hello": "IPFS"}',
    ContentType="application/json"
)

# List files
response = s3.list_objects_v2(Bucket="my-project")
for obj in response.get("Contents", []):
    print(obj["Key"], obj["Size"])

# Download
result = s3.get_object(Bucket="my-project", Key="data.json")
print(result["Body"].read())

Ejemplo en Go

go
package main

import (
    "context"
    "fmt"
    "strings"

    "github.com/aws/aws-sdk-go-v2/aws"
    "github.com/aws/aws-sdk-go-v2/credentials"
    "github.com/aws/aws-sdk-go-v2/service/s3"
)

func main() {
    client := s3.New(s3.Options{
        BaseEndpoint: aws.String("https://s3.ipfs.ninja"),
        Region:       "us-east-1",
        Credentials:  credentials.NewStaticCredentialsProvider("bws_628bba35", "bws_628bba35e9e0...", ""),
        UsePathStyle: true,
    })

    _, err := client.PutObject(context.TODO(), &s3.PutObjectInput{
        Bucket:      aws.String("my-project"),
        Key:         aws.String("hello.txt"),
        Body:        strings.NewReader("Hello, IPFS!"),
        ContentType: aws.String("text/plain"),
    })
    if err != nil {
        panic(err)
    }
    fmt.Println("Uploaded!")
}

Diferencias con Amazon S3

CaracterísticaAmazon S3IPFS Ninja S3
Modelo de almacenamientoObjetos mutablesDireccionamiento por contenido (CIDs inmutables)
Comportamiento al sobrescribirReemplaza el objeto en el sitioCrea un nuevo CID, el CID anterior sigue accesible
VersionadoSoportadoNo soportado (usa CIDs para versionar)
Cifrado del lado del servidorSoportadoNo soportado (el contenido está en IPFS)
Políticas de ciclo de vidaSoportadasNo soportadas
Políticas de bucket / ACLsSoportadasUsa modos de acceso del gateway
URLs prefirmadasSoportadasUsa tokens de subida firmados
Tamaño máximo de objeto5 TB5 GB (multipart), 100 MB (PUT individual)
RegionesMulti-regionSolo us-east-1
Valor de ETagHash MD5IPFS CID
Headers adicionalesS3 estándarx-amz-meta-cid (IPFS CID)

Migración desde Amazon S3

Reemplaza la configuración de tu cliente S3:

diff
 const s3 = new S3Client({
+  endpoint: "https://s3.ipfs.ninja",
   credentials: {
-    accessKeyId: "AKIA...",
-    secretAccessKey: "wJalrX..."
+    accessKeyId: "bws_628bba35",
+    secretAccessKey: "bws_628bba35e9e0..."
   },
   region: "us-east-1",
+  forcePathStyle: true
 });

Tus llamadas existentes a PutObject, GetObject, ListObjectsV2 y DeleteObject funcionan sin cambios.

Migración desde Filebase

Reemplaza la URL del endpoint:

diff
 const s3 = new S3Client({
-  endpoint: "https://s3.filebase.com",
+  endpoint: "https://s3.ipfs.ninja",
   credentials: {
-    accessKeyId: "FILEBASE_KEY",
-    secretAccessKey: "FILEBASE_SECRET"
+    accessKeyId: "bws_628bba35",
+    secretAccessKey: "bws_628bba35e9e0..."
   },
   region: "us-east-1",
   forcePathStyle: true
 });