Query Pins

Endpoint

/data/pinList

Description

This endpoint returns data on what content the sender has pinned to IPFS through Pinata.

The purpose of this endpoint is to provide insight into what is being pinned, and how long it has been pinned.

The results of this call can be filtered using multiple query parameters that will be discussed below.

Type

GET

Headers

pinata_api_key: (put your personal pinata api key here)

pinata_secret_api_key: (put your personal pinata secret api key here)

OR

Authorization: Bearer (put your pinata JWT here)

Request Query

You have the option to filter your pin list based on a number of different options.

To add a filter, add your query parameter to the end of the request URL by first adding ? and then filterParameter=filterValue.

For example, this request will only retrieve records for the content currently pinned:

https://api.pinata.cloud/data/pinList?status=pinned

To add a second filter, simply add & and then secondFilterParameter=filterValue to the end of the request URL.

For example, this request will only retrieve records that were pinned after January 1st, 2019 GMT:

https://api.pinata.cloud/data/pinList?status=pinned&pinStart=2019-01-01T00:00:00.000Z

The list of available filters is as follows:

hashContains: (string) - Filter on alphanumeric characters inside of pin hashes. Hashes which do not include the characters passed in will not be returned.
pinStart: (must be in ISO_8601 format) - Exclude pin records that were pinned before the passed in "pinStart" datetime.
pinEnd: (must be in ISO_8601 format) - Exclude pin records that were pinned after the passed in "pinEnd" datetime.
unpinStart: (must be in ISO_8601 format) - Exclude pin records that were unpinned before the passed in "unpinStart" datetime.
unpinEnd: (must be in ISO_8601 format) - Exclude pin records that were unpinned after the passed in "unpinEnd" datetime.
pinSizeMin: (integer) - The minimum byte size that pin record you're looking for can have
pinSizeMax: (integer) - The maximum byte size that pin record you're looking for can have
status: (string) -
* Pass in "all" for both pinned and unpinned records
* Pass in "pinned" for just pinned records (hashes that are currently pinned)
* Pass in "unpinned" for just unpinned records (previous hashes that are no longer being pinned on pinata)
pageLimit: (integer) - This sets the amount of records that will be returned per API response. (Max 1000)
pageOffset: (integer) - This tells the API how far to offset the record responses. For example, if there's 30 records that match your query, and you passed in a pageLimit of 10, providing a pageOffset of 10 would return records 11-20.

Metadata Querying

You also have the option to query your content on the associated metadata that may have been included with the content when it was uploaded through either the PinFileToIPFS or PinJSONToIPFS endpoints.

These queries look very similar to the default parameters but are slightly more complex.

Here are few simple examples, with added explanation afterward.

To query on the name you provided for your pin, your query would take this form:

?metadata[name]=exampleName

(this will match on names that contain the string of characters provided as a value. For added specificity, please include the full name you're trying to find).

To query on the metadata key-value attributes:

?metadata[keyvalues]={"exampleKey":{"value":"exampleValue","op":"exampleOp"}}

Or:

?metadata[keyvalues][exampleKey]={"value":"exampleValue","op":"exampleOp"}

To query on both the metadata name and multiple key-value attributes:

?metadata[name]=exampleName&metadata[keyvalues]={"exampleKey":{"value":"exampleValue","op":"exampleOp"},"exampleKey2":{"value":"exampleValue2","op":"exampleOp2"}}

Explaining the "value" and "op" key / values

As seen above, each query on custom values takes the form of an object with a "value" key and an "op" key.

The "value" is fairly straightforward. This is simply the value that you wish your query operation to be applied to. These values can be:

  • Strings

  • Numbers (integers or decimals)

  • Dates (Provided in ISO_8601 format)

The "op" is what query operation will be applied to the value you provided. The following opcodes are available to query with:

  • "gt" - (greater than)

  • "gte" - (greater than or equal)

  • "lt" - (less than)

  • "lte" - (less than or equal)

  • "ne" - (not equal to)

  • "eq" - (equal to)

  • "between" - (When querying with the 'between' operation, you need to supply a 'secondValue' to be consumed by the query operation)

For Example:

?metadata[keyvalues]={"exampleKey":{"value":"2018-01-01 00:00:00.000+00","secondValue":"2018-02-01 00:00:00.000+00","op":"between"}}

  • "notBetween" - (When querying with the 'notBetween' operation, you need to supply a 'secondValue' to be consumed by the query operation)

For Example:

?metadata[keyvalues]={"exampleKey":{"value":4.00,"secondValue":5.50,"op":"notBetween"}}

  • "like" - (you can use this to find values that are similar to what you've passed in)

For example, this query would find all entries that begin with "testValue". A % before your value means anything can come before it, and a % sign after means any characters can come after it. So %testValue% would contain all entries containing the characters "testValue".

?metadata[keyvalues]={"exampleKey":{"value":"testValue%","op":"like"}}

  • "notLike" - (you can use this to find values that do not contain the character string you've passed in)

  • "iLike" - (The case insensitive version of the "like" opcode)

  • "notILike" - (The case insensitive version of the "notLike" opcode)

  • "regexp" - (Regular expression matching)

  • "iRegexp" - (Case insensitive regular expression matching)

Response

The response for this call takes the form of a JSON object seen below. Each item in the "rows" array represents a pin record that matched the query parameters you passed in.

{
count: (this is the total number of pin records that exist for the query filters you passed in),
rows: [
{
id: (the id of your pin instance record),
ipfs_pin_hash: (the IPFS multi-hash for the content you pinned),
size: (this is how large (in bytes) the content pinned is),
user_id: (this is your user id for Pinata),
date_pinned: (This is the timestamp for when this content was pinned - represented in ISO 8601 format),
date_unpinned: (This is the timestamp for when this content was unpinned (if null, then you still have the content pinned on Pinata),
metadata: {
name: (this will be the name of the file originally upuloaded, or the custom name you set),
keyvalues: {
exampleCustomKey: "exampleCustomValue",
exampleCustomKey2: "exampleCustomValue2",
...
}
},
regions: [
{
regionId: (region this content is expected to be pinned in),
desiredReplicationCount: (the number of replications desired in this region for this content),
currentReplicationCount: (the number of times this content has been replicated so far)
}
]
},
{
same record format as above
}
.
.
.
]
}

Postman Example

Text of the example endpoint:

https://api.pinata.cloud/data/pinList?status=pinned&metadata[name]=exampleName&metadata[keyvalues]={"exampleKey":{"value":"exampleValue","op":"exampleOp"},"exampleKey2":{"value":"exampleValue2","op":"exampleOp2"}}

JavaScript With Axios Example

In the javascript example below, we pass in our API keys from elsewhere (hopefully in a secure way).

We also pass in the query parameters in the form of a JSON object.

const axios = require('axios');
export const userPinList = (pinataApiKey, pinataSecretApiKey, queryParams) => {
let queryString = '?';
if (queryParams.hashContains) {
queryString = queryString + `hashContains=${queryParams.hashContains}&`;
}
if (queryParams.pinStartDate) {
queryString = queryString + `pinStart=${queryParams.pinStartDate}&`;
}
if (queryParams.pinEndDate) {
queryString = queryString + `pinEnd=${queryParams.pinEndDate}&`;
}
if (queryParams.unpinStartDate) {
queryString = queryString + `unpinStart=${queryParams.unpinStartDate}&`;
}
if (queryParams.unpinEndDate) {
queryString = queryString + `unpinEnd=${queryParams.unpinEndDate}&`;
}
if (queryParams.selectedPinStatus) {
queryString = queryString + `status=${queryParams.selectedPinStatus}&`;
}
if (queryParams.unpinEndDate) {
queryString = queryString + `unpinEnd=${queryParams.unpinEndDate}&`;
}
if (queryParams.unpinEndDate) {
queryString = queryString + `unpinEnd=${queryParams.unpinEndDate}&`;
}
if (queryParams.pageLimit) {
queryString = queryString + `pageLimit=${queryParams.pageLimit}&`;
}
if (queryParams.pageOffset) {
queryString = queryString + `pageOffset=${queryParams.pageOffset}&`;
}
if (queryParams.nameContains) {
queryString = queryString + `metadata[name]=${queryParams.nameContains}&`;
}
//Make sure keyvalues are properly formatted as described earlier in the docs.
if (queryParams.keyvalues) {
const stringKeyValues = JSON.stringify(queryParams.keyvalues);
queryString = queryString + `metadata[keyvalues]=${stringKeyValues}`;
}
const url = `https://api.pinata.cloud/data/pinList${queryString}`;
return axios
.get(url, {
headers: {
pinata_api_key: pinataApiKey,
pinata_secret_api_key: pinataSecretApiKey
}
})
.then(function (response) {
//handle response here
})
.catch(function (error) {
//handle error here
});
};

We want your feedback!

Have a suggestion? Have a complaint? Confused about something in the documentation? Just want to say hi?

We want to make Pinata the best product available. That involves listening to our users and addressing their needs.

Send us an email at [email protected] and we'll see how we can help.