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
}'import requests
url = "https://api.pinata.cloud/pinning/pinFileToIPFS"
files = { "file": ("example-file", open("example-file", "rb")) }
payload = {
"pinataMetadata": "{
\"name\": \"Pinnie.json\"
}",
"pinataOptions": "{
\"cidVersion\": 1
}"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('file', 'readstream');
form.append('pinataMetadata', '{
"name": "Pinnie.json"
}');
form.append('pinataOptions', '{
"cidVersion": 1
}');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.pinata.cloud/pinning/pinFileToIPFS', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.pinata.cloud/pinning/pinFileToIPFS",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\nreadstream\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataMetadata\"\r\n\r\n{\r\n \"name\": \"Pinnie.json\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataOptions\"\r\n\r\n{\r\n \"cidVersion\": 1\r\n}\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.pinata.cloud/pinning/pinFileToIPFS"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\nreadstream\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataMetadata\"\r\n\r\n{\r\n \"name\": \"Pinnie.json\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataOptions\"\r\n\r\n{\r\n \"cidVersion\": 1\r\n}\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.pinata.cloud/pinning/pinFileToIPFS")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\nreadstream\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataMetadata\"\r\n\r\n{\r\n \"name\": \"Pinnie.json\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataOptions\"\r\n\r\n{\r\n \"cidVersion\": 1\r\n}\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pinata.cloud/pinning/pinFileToIPFS")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\nreadstream\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataMetadata\"\r\n\r\n{\r\n \"name\": \"Pinnie.json\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataOptions\"\r\n\r\n{\r\n \"cidVersion\": 1\r\n}\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"IpfsHash": "<string>",
"PinSize": 123,
"Timestamp": "<string>",
"isDuplicate": true
}Pinning
Pin File to IPFS
Upload a file to Pinata to be pinned to IPFS
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
}'import requests
url = "https://api.pinata.cloud/pinning/pinFileToIPFS"
files = { "file": ("example-file", open("example-file", "rb")) }
payload = {
"pinataMetadata": "{
\"name\": \"Pinnie.json\"
}",
"pinataOptions": "{
\"cidVersion\": 1
}"
}
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('file', 'readstream');
form.append('pinataMetadata', '{
"name": "Pinnie.json"
}');
form.append('pinataOptions', '{
"cidVersion": 1
}');
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
options.body = form;
fetch('https://api.pinata.cloud/pinning/pinFileToIPFS', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.pinata.cloud/pinning/pinFileToIPFS",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\nreadstream\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataMetadata\"\r\n\r\n{\r\n \"name\": \"Pinnie.json\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataOptions\"\r\n\r\n{\r\n \"cidVersion\": 1\r\n}\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: multipart/form-data"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.pinata.cloud/pinning/pinFileToIPFS"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\nreadstream\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataMetadata\"\r\n\r\n{\r\n \"name\": \"Pinnie.json\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataOptions\"\r\n\r\n{\r\n \"cidVersion\": 1\r\n}\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.pinata.cloud/pinning/pinFileToIPFS")
.header("Authorization", "Bearer <token>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\nreadstream\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataMetadata\"\r\n\r\n{\r\n \"name\": \"Pinnie.json\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataOptions\"\r\n\r\n{\r\n \"cidVersion\": 1\r\n}\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.pinata.cloud/pinning/pinFileToIPFS")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\nreadstream\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataMetadata\"\r\n\r\n{\r\n \"name\": \"Pinnie.json\"\r\n}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"pinataOptions\"\r\n\r\n{\r\n \"cidVersion\": 1\r\n}\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"IpfsHash": "<string>",
"PinSize": 123,
"Timestamp": "<string>",
"isDuplicate": true
}Guides
Blobs
Blobs
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()
URL
URL
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");
base64
base64
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
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.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()
import { useState } from "react";
function App() {
const [selectedFile, setSelectedFile]: any = useState();
const changeHandler = (event: any) => {
setSelectedFile(event.target.files);
};
const handleSubmission = async () => {
try {
const formData = new FormData();
Array.from(selectedFile).forEach((file) => {
formData.append("file", file);
});
const metadata = JSON.stringify({
name: "File name",
});
formData.append("pinataMetadata", metadata);
const options = JSON.stringify({
cidVersion: 0,
});
formData.append("pinataOptions", options);
const res = await fetch(
"https://api.pinata.cloud/pinning/pinFileToIPFS",
{
method: "POST",
headers: {
Authorization: `Bearer ${import.meta.env.VITE_PINATA_JWT}`,
},
body: formData,
}
);
const resData = await res.json();
console.log(resData);
} catch (error) {
console.log(error);
}
};
return (
<>
<label className="form-label"> Choose File</label>
<input
directory=""
webkitdirectory=""
type="file"
onChange={changeHandler}
/>
<button onClick={handleSubmission}>Submit</button>
</>
);
}
export default App;
import FormData from "form-data"
const pinDirectoryToIPFS = async () => {
try {
const folder = "json";
const json1 = { hello: "world" };
const json2 = { hello: "world2" };
const blob1 = new Blob([JSON.stringify(json1, null, 2)], {
type: "application/json",
});
const blob2 = new Blob([JSON.stringify(json2, null, 2)], {
type: "application/json",
});
const files = [
new File([blob1], "hello.json", { type: "application/json" }),
new File([blob2], "hello2.json", { type: "application/json" }),
];
const data = new FormData();
Array.from(files).forEach((file) => {
// If you are not using `fs` you might need to specify the folder path along with the filename
data.append("file", file, `${folder}/${file.name}`);
});
const pinataMetadata = JSON.stringify({
name: `${folder}`,
});
data.append("pinataMetadata", pinataMetadata);
const res = await fetch("https://api.pinata.cloud/pinning/pinFileToIPFS", {
method: "POST",
headers: {
Authorization: `Bearer ${PINATA_JWT}`,
},
body: data,
});
const resData = await res.json();
console.log(resData);
} catch (error) {
console.log(error);
}
};
pinDirectoryToIPFS();
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
multipart/form-data
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)" }
⌘I