Skip to main content
POST
/
pinning
/
pinFileToIPFS
Pin File to IPFS
curl --request POST \
  --url https://api.pinata.cloud/pinning/pinFileToIPFS \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: multipart/form-data' \
  --form file=@example-file \
  --form 'pinataMetadata={
  "name": "Pinnie.json"
}' \
  --form 'pinataOptions={
  "cidVersion": 1
}'
{
  "IpfsHash": "<string>",
  "PinSize": 123,
  "Timestamp": "<string>",
  "isDuplicate": true
}

Guides

Usually you can pass a Blob directly into the request but to help guarantee success we recommend passing it into a File object.
Pin Blob
const JWT = 'YOUR_PINATA_JWT';

async function pinFileToIPFS() {
  try {
    const text = "Hello World!";
    const blob = new Blob([text], { type: "text/plain" });
    const file = new File([blob], "hello-world.txt")
    const data = new FormData();
    data.append("file", file);

    const res = await fetch("https://api.pinata.cloud/pinning/pinFileToIPFS", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${JWT}`,
      },
      body: data,
    });
    const resData = await res.json();
    console.log(resData);
  } catch (error) {
    console.log(error);
  }
};

await pinFileToIPFS()
To upload a file from an external URL you can stream the contents into an arrayBuffer, which then gets passed into a new Blob that can then be uploaded to Pinata.
Upload by URL
const JWT = "YOUR_PINATA_JWT";

async function uploadByURL(url) {
  try {
    const urlStream = await fetch(url);
    const arrayBuffer = await urlStream.arrayBuffer();
    const blob = new Blob([arrayBuffer]);
    const file = new File([blob], "file")
    const data = new FormData();
    data.append("file", file);

    const upload = await fetch(
      "https://api.pinata.cloud/pinning/pinFileToIPFS",
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${JWT}`,
        },
        body: data,
      }
    );
    const uploadRes = await upload.json();
    console.log(uploadRes);
  } catch (error) {
    console.log(error);
  }
}

await uploadByURL("https://pocketcast.cloud/og.png");
To upload a file in base64 simply turn the contents into a buffer that is passed into a Blob.
Upload base64
const JWT = "YOUR_PINATA_JWT";

async function uploadBase64(base64String) {
  try {
    const buffer = Buffer.from(base64String, "base64");
    const blob = new Blob([buffer]);
    const file = new File([blob], "file");
    const data = new FormData();
    data.append("file", file);

    const upload = await fetch(
      "https://api.pinata.cloud/pinning/pinFileToIPFS",
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${JWT}`,
        },
        body: data,
      },
    );
    const uploadRes = await upload.json();
    console.log(uploadRes);
  } catch (error) {
    console.log(error);
  }
}

await uploadBase64("SGVsbG8gZnJvbSBQaW5hdGEhIDop");
Folders can also be uploaded via the API by creating an array of files and mapping over them to add them to the form data. This is different then having a single file entry and having multiple files for that one entry, which does not work.
import fs from "fs"
import FormData from "form-data"
import rfs from "recursive-fs"
import basePathConverter from "base-path-converter"
import got from 'got'

const pinDirectoryToPinata = async () => {
  const url = `https://api.pinata.cloud/pinning/pinFileToIPFS`;
  const src = "PATH_TO_FOLDER";
  var status = 0;
  try {

    const { dirs, files } = await rfs.read(src);

    let data = new FormData();

    for (const file of files) {
      data.append(`file`, fs.createReadStream(file), {
        filepath: basePathConverter(src, file),
      });
    }

    const response = await got(url, {
      method: 'POST',
      headers: {
        "Authorization": "Bearer PINATA_API_JWT"
      },
      body: data
  })
		.on('uploadProgress', progress => {
			console.log(progress);
		});

	console.log(JSON.parse(response.body));
  } catch (error) {
    console.log(error);
  }
};

pinDirectoryToPinata()

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Body

multipart/form-data
file
file
required
pinataMetadata
object

Optional stringified object

Example:

"{\"name\":\"Test file\"}"

pinataOptions
object

Optional stringified object

Example:

"{\"cidVersion\":0}"

Response

200 - application/json

{ "IpfsHash": "This is the IPFS multi-hash (CID) provided back for your content," "PinSize": "This is how large (in bytes) the content you just pinned is," "Timestamp": "This is the timestamp for your content pinning (represented in ISO 8601 format)" }

IpfsHash
string
PinSize
integer
Timestamp
string
isDuplicate
boolean
I