Pinning Files
With Pinata, there are a few ways you can pin files to IPFS!
API & SDKs
If you’re a developer that needs to build decentralized applications, then you will likely want to use the Pinata API or Pinata SDK. These make it simple to upload files or raw JSON to IPFS!
Using the SDK
The Pinata Node SDK is designed to work in a backend environment, so if you are trying to upload in a front end client, please observe the API example.
const fs = require('fs');
const pinataSDK = require('@pinata/sdk');
const pinata = new pinataSDK({ pinataJWTKey: 'yourPinataJWTKey'});
const stream = fs.createReadStream('./yourfile.png');
const res = await pinata.pinFileToIPFS(stream)`
The SDK is also equipped to handle folders as well as files, so you can pass a directory into the file path to upload it.
const fs = require('fs');
const pinataSDK = require('@pinata/sdk');
const pinata = new pinataSDK({ pinataJWTKey: 'yourPinataJWTKey'});
const stream = fs.createReadStream('./some-directory');
const res = await pinata.pinFileToIPFS(stream)`
Using the API
The API is a bit more flexible, as it can be used in multiple languages or environments, and is sometimes preferred for client side uploads. With that, we should express warning in that client side applications will expose API keys.
Using your API Keys in a client side application will expose them!!
Here is an example of how you could upload with the API:
const JWT = "YOUR_PINATA_JWT";
const fs = require("fs");
async function pinFileToIPFS() {
try {
const formData = new FormData();
const src = "path/to/file.png";
const file = fs.createReadStream(src);
formData.append("file", file);
const pinataMetadata = JSON.stringify({
name: "File name",
});
formData.append("pinataMetadata", pinataMetadata);
const pinataOptions = JSON.stringify({
cidVersion: 0,
});
formData.append("pinataOptions", pinataOptions);
const res = await fetch("https://api.pinata.cloud/pinning/pinFileToIPFS", {
method: "POST",
headers: {
Authorization: `Bearer YOUR_PINATA_JWT`,
},
body: formData,
});
const resData = await res.json();
console.log(resData);
} catch (error) {
console.log(error);
}
}
The API will expect a File
, Blob
, or a readableStream
for any files uploaded. Here is an example of turning raw data into a Blob
and then uploading it.
const JWT = 'YOUR_PINATA_JWT';
async function pinFileToIPFS() {
try {
const text = "Hello World!";
const blob = new Blob([text], { type: "text/plain" });
const data = new FormData();
data.append("file", blob);
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);
}
};
Another example of this in action is turning a URL stream into an arrayBuffer
, which then gets passed into a new Blob
that can then be uploaded to Pinata.
const JWT = "YOUR_PINATA_JWT";
export default async function uploadByURL(url) {
try {
const urlStream = await fetch(url);
const arrayBuffer = await urlStream.arrayBuffer();
const blob = new Blob([arrayBuffer]);
const data = new FormData();
data.append("file", blob);
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);
}
}
uploadByURL("https://pocketcast.cloud/og.png");
Folders
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.
We also have other tools like the Pinata CLI or Next.js Starter which can be used to upload using API Keys!
Web App
If you’re non-technical, you can use Pinata App to upload files, perfect if you just want to get started with NFTs and IPFS! It’s as simple as clicking the “Upload” button in the top right corner of the files page. Select your file, give it a name, then upload. Once it’s complete you’ll see it listed in the files page.
Start uploading by signing up for a free account!
Pin by CID
Another way you can upload content to Pinata is by transferring content that is already on IPFS. This could be CIDs that are on your own local IPFS node or another IPFS pinning service! You can do this with the “Pin by CID” button in the web app, like so:
Or you can pin by CID with our API using the Pin By CID endpoint:
const JWT = 'YOUR_PINATA_JWT';
async function pinByCID() {
try {
const data = JSON.stringify({
hashToPin: 'bafkreih5aznjvttude6c3wbvqeebb6rlx5wkbzyppv7garjiubll2ceym4'
})
const res = await fetch("https://api.pinata.cloud/pinning/pinByHash",
method: "POST",
headers: {
contentType: 'application/json',
Authorization: `Bearer ${JWT}`,
},
body: data,
);
const resData = await res.json();
console.log(resData);
} catch (error) {
console.log(error);
}
};
This will result in a request_id
and Pinata will start looking for the file. Progress can be checked by using the list pinning jobs endpoint.
const JWT = 'YOUR_PINATA_JWT';
async function pinByCID() {
try {
const data = JSON.stringify({
hashToPin: 'bafkreih5aznjvttude6c3wbvqeebb6rlx5wkbzyppv7garjiubll2ceym4'
})
const res = await fetch("https://api.pinata.cloud/pinning/pinJobs",
method: "GET",
headers: {
contentType: 'application/json',
Authorization: `Bearer ${JWT}`,
},
body: data,
);
const resData = await res.json();
console.log(resData);
} catch (error) {
console.log(error);
}
};
All possible filters are included in the API reference below, but these are the possible “status” filters:
Filter by the status of the job in the pinning queue (see potential statuses
below) - prechecking
Pinata is running preliminary validations on your pin
request. - searching
Pinata is actively searching for your content on the
IPFS network. This may take some time if your content is isolated. -
retrieving
Pinata has located your content and is now in the process of
retrieving it. - expired
Pinata wasn’t able to find your content after a day
of searching the IPFS network. Please make sure your content is hosted on the
IPFS network before trying to pin again. - over_free_limit
Pinning this
object would put you over the free tier limit. Please add a credit card to
continue pinning content. - over_max_size
This object is too large of an
item to pin. If you’re seeing this, please contact us for a more custom
solution. - invalid_object
The object you’re attempting to pin isn’t
readable by IPFS nodes. Please contact us if you receive this, as we’d like to
better understand what you’re attempting to pin. - bad_host_node
You
provided a host node that was either invalid or unreachable. Please make sure
all provided host nodes are online and reachable.
Predetermining the CID
If you find yourself in a position where you want to pre-determine the CID before uploading you can use the multiformats
library. The key is making sure you use raw
codec and use blobs just like the Pinata API accepts to get the same results.
import { CID } from 'multiformats/cid'
import * as raw from 'multiformats/codecs/raw'
import { sha256 } from 'multiformats/hashes/sha2'
const JWT = "YOUR_PINATA_JWT"
async function main(){
try {
const text = "Hello World!";
const blob = new Blob([text], { type: "text/plain" });
const unit8array = new Uint8Array(await blob.arrayBuffer());
const bytes = raw.encode(unit8array)
const hash = await sha256.digest(bytes)
const cid = CID.create(1, raw.code, hash)
console.log(cid.toString())
} catch(error) {
console.log(error)
}
}
async function pinFileToIPFS() {
try {
const text = "Hello World!";
const blob = new Blob([text], { type: "text/plain" });
const data = new FormData();
data.append("file", blob);
const options = JSON.stringify({
cidVersion: 1
})
data.append("pinataOptions", options)
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.IpfsHash);
} catch (error) {
console.log(error);
}
};
main()
pinFileToIPFS()