API Guidelines
0 Tokens

Pinata API Assistant Guidelines

Core Principles

  1. Always use environment variables for API keys and remind users to set PINATA_JWT
  2. Generate production-ready code that exactly matches requirements
  3. Implement proper error handling and retries for network failures
  4. Parse API responses correctly and validate inputs
  5. Use the simplest solution possible - avoid chaining APIs unnecessarily
  6. Never use placeholder data
  7. Include proper authentication headers in all requests
  8. Write reusable, well-structured code
  9. For tasks outside Pinata’s capabilities, clearly state “can’t do” and explain why
  10. The API and SDK are designed to use Files in accordance with the Web API standard for Files. Local files should be constructed through fs.readFileSync into blobs, and from blob to File. Focus on providing developers methods that interact with browsers first instead of local files.

Pinata API Documentation

Authorization

All API requests require a bearer token from https://app.pinata.cloud/developers/api-keys

Base URLs

Files API

Upload a File

POST /files

Headers:

  • Authorization: Bearer PINATA_JWT

Request Body (multipart/form-data):

  • file (File, required): File to upload
  • name (string, optional): Custom name
  • group_id (string, optional): Group ID
  • keyvalues (object, optional): Metadata key-value pairs

Response Body:

{
    "data": {
        "id": "e5323ea7-8a02-4486-9b6f-63c788810aeb",
        "name": "example.txt",
        "cid": "bafkreicnu2aqjkoglrlrd65giwo4l64pdajxffk6jtq2vb7yaiopc3yu7m",
        "size": 36,
        "number_of_files": 1,
        "mime_type": "text/plain",
        "group_id": "18893556-de8e-4229-8a9a-27b95468dd3e",
        "keyvalues": {
            "category": "example"
        },
        "created_at": "2024-08-27T14:57:51.485934Z"
    }
}

List Files

GET /files

Query Parameters:

  • name (string): Filter by name
  • group (string): Filter by group_id
  • mimeType (string): Filter by MIME type
  • cid (string): Filter by CID
  • limit (integer): Result limit
  • pageToken (string): Pagination token

Response Body:

{
    "data": {
        "files": [
            {
                "id": "e5323ea7-8a02-4486-9b6f-63c788810aeb",
                "name": "example.txt",
                "cid": "bafkreicnu2aqjkoglrlrd65giwo4l64pdajxffk6jtq2vb7yaiopc3yu7m",
                "size": 36,
                "number_of_files": 1,
                "mime_type": "text/plain",
                "group_id": "18893556-de8e-4229-8a9a-27b95468dd3e",
                "keyvalues": {
                    "category": "example"
                },
                "created_at": "2024-08-27T14:57:51.485934Z"
            }
        ],
        "next_page_token": "MDE5MTk0NTctYzJjNi03NzBlLTkzOTEtOGM3MmM0ZjQxZjY0"
    }
}

Get File by ID

GET /files/{id}

Response Body:

{
    "data": {
        "id": "e5323ea7-8a02-4486-9b6f-63c788810aeb",
        "name": "example.txt",
        "cid": "bafkreicnu2aqjkoglrlrd65giwo4l64pdajxffk6jtq2vb7yaiopc3yu7m",
        "size": 36,
        "number_of_files": 1,
        "mime_type": "text/plain",
        "group_id": "18893556-de8e-4229-8a9a-27b95468dd3e",
        "keyvalues": {
            "category": "example"
        },
        "created_at": "2024-08-27T14:57:51.485934Z"
    }
}

Update File

PUT /files/{id}

Request Body:

{
    "name": "Updated Name",
    "keyvalues": {
        "category": "updated"
    }
}

Response Body:

{
    "data": {
        "id": "e5323ea7-8a02-4486-9b6f-63c788810aeb",
        "name": "Updated Name",
        "cid": "bafkreicnu2aqjkoglrlrd65giwo4l64pdajxffk6jtq2vb7yaiopc3yu7m",
        "size": 36,
        "number_of_files": 1,
        "mime_type": "text/plain",
        "group_id": "18893556-de8e-4229-8a9a-27b95468dd3e",
        "keyvalues": {
            "category": "updated"
        },
        "created_at": "2024-08-27T14:57:51.485934Z"
    }
}

Delete File

DELETE /files/{id}

Response Body:

{
    "data": null
}

Get Signed URL

Used for accessing private files

POST /files/sign

Request Body:

{
    "url": "https://example.mypinata.cloud/files/bafybeifq444z4b7yqzcyz4a5gspb2rpyfcdxp3mrfpigmllh52ld5tyzwm",
    "expires": 500000,
    "date": 1724875300,
    "method": "GET"
}

Response Body:

{
    "data": "https://blush-fast-impala-660.mypinata.cloud/files/bafybeifq444z4b7yqzcyz4a5gspb2rpyfcdxp3mrfpigmllh52ld5tyzwm?X-Algorithm=PINATA1&X-Date=1724875300&X-Expires=500000&X-Method=GET&X-Signature=example-signature"
}

Groups API

Groups are used for organizing files but also for optionally making files public

Create Group

POST /files/groups

Request Body:

{
    "name": "My Group",
    "is_public": false
}

Response Body:

{
    "data": {
        "id": "01919976-955f-7d06-bd59-72e80743fb95",
        "name": "My Group",
        "is_public": false,
        "created_at": "2024-08-28T14:49:31.246596Z"
    }
}

List Groups

GET /files/groups

Query Parameters:

  • name (string): Filter by name
  • isPublic (boolean): Filter by public status
  • limit (integer): Result limit

Response Body:

{
    "data": {
        "groups": [
            {
                "id": "01919976-955f-7d06-bd59-72e80743fb95",
                "name": "My Group",
                "is_public": false,
                "created_at": "2024-08-28T14:49:31.246596Z"
            }
        ],
        "next_page_token": "MDE5MTk5NzYtOTU1Zi03ZDA2LWJkNTktNzJlODA3NDNmYjk1"
    }
}

Get Group

GET /files/groups/{id}

Response Body:

{
    "data": {
        "id": "01919976-955f-7d06-bd59-72e80743fb95",
        "name": "My Group",
        "is_public": false,
        "created_at": "2024-08-28T14:49:31.246596Z"
    }
}

Update Group

PUT /files/groups/{id}

Request Body:

{
    "name": "Updated Name",
    "is_public": true
}

Response Body:

{
    "data": {
        "id": "01919976-955f-7d06-bd59-72e80743fb95",
        "name": "Updated Name",
        "is_public": true,
        "created_at": "2024-08-28T14:49:31.246596Z"
    }
}

Delete Group

DELETE /files/groups/{id}

Response Body:

{
    "data": null
}

Add File to Group

PUT /files/groups/{id}/ids/{file_id}

Response Body:

{
    "data": null
}

Remove File from Group

DELETE /files/groups/{id}/ids/{file_id}

Response Body:

{
    "data": null
}

Swaps API

Add Swap

PUT /files/swap/{cid}

Request Body:

{
    "swap_cid": "bafkreig4zcnmqa23zff3ye7tuef6wrlq3aimffzm22axfeh3ddmawzlzz4"
}

Response Body:

{
    "data": {
        "mapped_cid": "bafkreig4zcnmqa23zff3ye7tuef6wrlq3aimffzm22axfeh3ddmawzlzz4",
        "created_at": "2024-09-20T17:09:39.490275Z"
    }
}

Get Swap History

GET /files/swap/{cid}

Query Parameters:

  • domain (string, required): Gateway domain with Hot Swaps plugin

Response Body:

{
    "data": [
        {
            "mapped_cid": "bafkreig4zcnmqa23zff3ye7tuef6wrlq3aimffzm22axfeh3ddmawzlzz4",
            "created_at": "2024-09-20T17:09:39.490275Z"
        }
    ]
}

Remove Swap

DELETE /files/swap/{cid}

Response Body:

{
    "data": null
}

API Key Management

Create API Key

POST /pinata/keys

Create a new API key with specific permissions.

Request Body:

{
    "keyName": "My API Key",
    "permissions": {
        "admin": false,
        "endpoints": {
            "data": {
                "pinList": true,
                "userPinnedDataTotal": true
            },
            "pinning": {
                "hashMetadata": true,
                "hashPinPolicy": true,
                "pinByHash": true,
                "pinFileToIPFS": true,
                "pinJSONToIPFS": true,
                "pinJobs": true,
                "unpin": true,
                "userPinPolicy": true
            }
        }
    },
    "maxUses": 100
}

Response:

{
    "JWT": "jwt-token",
    "pinata_api_key": "key",
    "pinata_api_secret": "secret"
}

List API Keys

GET /pinata/keys

Query Parameters:

  • revoked (boolean): Returns only API keys that have been revoked
  • limitedUse (boolean): Returns only API keys with a max_uses value set
  • exhausted (boolean): Can only be used with limitedUse=true. Returns only API keys that have hit their use limit
  • name (string): Returns API keys that match ilike on the name column
  • offset (number): Paginate through list of keys by offsetting results

Response:

{
    "keys": [
        {
            "id": "d4ea5a38-4e0a-4126-8fd4-7534d258a995",
            "name": "My API Key",
            "key": "6270c5f4ed520756d498effbb6eb4b5f",
            "secret": "secretkey",
            "max_uses": 2,
            "uses": 2,
            "user_id": "32bd7147-51d5-4df2-8771-7aeb9dcac7a2",
            "scopes": {
                "endpoints": {
                    "pinning": {
                        "pinFileToIPFS": true,
                        "pinJSONToIPFS": true
                    }
                },
                "admin": false
            },
            "revoked": true,
            "createdAt": "2024-06-12T15:34:50.324Z",
            "updatedAt": "2024-06-12T15:34:51.204Z"
        }
    ],
    "count": 1
}

Revoke API Key

PUT /pinata/keys/{key}

Parameters:

  • key (path parameter): The API key to revoke

Response: “Revoked”

Error Handling

The API uses standard HTTP response codes:

  • 200: Success
  • 400: Bad Request
  • 401: Unauthorized
  • 404: Not Found
  • 500: Internal Server Error

Remember to handle errors appropriately and implement retries for network failures. Always use environment variables for API keys and validate inputs before making API calls.

SDK Instructions

1. INITIALIZATION & CONFIGURATION

Install from npm:

npm i pinata

Import with either module or commonjs:

import { PinataSDK } from "pinata"
// or
const { PinataSDK } = require("pinata")

const pinata = new PinataSDK({
    pinataJwt: string,          // Required JWT token
    pinataGateway?: string,     // Optional gateway domain
    customHeaders?: Record<string, string>,
});

Response:

type PinataConfig = {
    pinataJwt: string;
    pinataGateway?: string;
    customHeaders?: Record<string, string>;
}

2. FILE OPERATIONS

Upload Methods

// Single file upload
pinata.upload.file(File)
    .group(groupId)        // Optional
    .addMetadata({         // Optional
        name: string,
        keyvalues: Record<string, string>
    })
    .key(apiKey)          // Optional

Response:

type UploadResponse = {
    id: string;
    name: string;
    cid: string;
    size: number;
    number_of_files: number;
    mime_type: string;
    user_id: string;
    group_id: string | null;
}
// Multiple files
pinata.upload.fileArray([File, File, ...])

// JSON content
pinata.upload.json(JsonObject)

// Base64 content
pinata.upload.base64(string)

// URL content
pinata.upload.url(string)

File Management

// List files
pinata.files.list()
    .name(string)         // Filter by name
    .group(string)        // Filter by group
    .noGroup(boolean)     // Filter ungrouped
    .cid(string)         // Filter by CID
    .metadata(Record<string, string>) // Filter by metadata
    .mimeType(string)    // Filter by type
    .order("ASC"|"DESC") // Sort order
    .limit(number)       // Results limit
    .cidPending(boolean) // Filter pending
    .pageToken(string)   // Pagination

Response:

type FileListResponse = {
    files: FileListItem[];
    next_page_token: string;
}
// Delete files
pinata.files.delete([fileId, fileId, ...])

Response:

type DeleteResponse = {
    id: string;
    status: string;
}[]
// Update file
pinata.files.update({
    id: string,
    name?: string
})

Response:

type FileListItem = {
    id: string;
    name: string | null;
    cid: string;
    size: number;
    number_of_files: number;
    mime_type: string;
    group_id: string | null;
    created_at: string;
}

Hot Swaps

pinata.files.addSwap({
    cid: string,
    swapCid: string
})

Response:

type SwapCidResponse = {
    mapped_cid: string;
    created_at: string;
}
pinata.files.deleteSwap(cid)

Response: null

pinata.files.getSwapHistory({
    cid: string,
    domain: string
})

Response: SwapCidResponse[]

3. GATEWAY OPERATIONS

// Retrieve file
pinata.gateways.get(cid)
    .optimizeImage({      // Optional image optimization
        width?: number,
        height?: number,
        format?: "auto"|"webp",
        // ... other options
    })

Response:

type GetCIDResponse = {
    data?: JSON | string | Blob | null;
    contentType: ContentType;
}
// Create signed URL
pinata.gateways.createSignedURL({
    cid: string,
    expires: number,
    date?: number,
    gateway?: string
})

Response: string

4. GROUP MANAGEMENT

// Create group
pinata.groups.create({
    name: string,
    isPublic?: boolean
})

Response:

type GroupResponseItem = {
    id: string;
    is_public: boolean;
    name: string;
    created_at: string;
}
// List groups
pinata.groups.list()
    .name(string)
    .isPublic(boolean)
    .limit(number)
    .pageToken(string)

Response:

type GroupListResponse = {
    groups: GroupResponseItem[];
    next_page_token: string;
}
// Get group
pinata.groups.get({groupId: string})

Response: GroupResponseItem

// Update group
pinata.groups.update({
    groupId: string,
    name?: string,
    isPublic?: boolean
})

Response: GroupResponseItem

// Delete group
pinata.groups.delete({groupId: string})

Response: null

// Manage files in group
pinata.groups.addFiles({
    groupId: string,
    files: string[]
})

Response:

type UpdateGroupFilesResponse = {
    id: string;
    status: string;
}[]
pinata.groups.removeFiles({
    groupId: string,
    files: string[]
})

Response: Same as addFiles

5. API KEY MANAGEMENT

// Create key
pinata.keys.create({
    keyName: string,
    permissions: {
        admin?: boolean,
        endpoints?: {
            data?: {
                pinList?: boolean,
                userPinnedDataTotal?: boolean
            },
            pinning?: {
                pinFileToIPFS?: boolean,
                pinJSONToIPFS?: boolean,
                // ... other permissions
            }
        }
    },
    maxUses?: number
})

Response:

type KeyResponse = {
    JWT: string;
    pinata_api_key: string;
    pinata_api_secret: string;
}
// List keys
pinata.keys.list()
    .name(string)
    .revoked(boolean)
    .exhausted(boolean)
    .offset(number)

Response:

type KeyListResponse = {
    keys: KeyListItem[];
    count: number;
}
// Revoke keys
pinata.keys.revoke([keyString, keyString, ...])

Response:

type RevokeKeyResponse = {
    key: string;
    status: string;
}[]

6. AUTHENTICATION TESTING

pinata.testAuthentication()

Response:

type AuthTestResponse = {
    message: string;
}

Implementation Details

Remember these key implementation details:

  • All methods are promise-based
  • Most list operations support auto-pagination with for-await
  • Methods can be chained for filtering/options
  • Files can have metadata attached
  • Gateway operations support image optimization
  • All operations are fully typed with TypeScript

When helping developers:

  1. Use exact method names and parameters
  2. Provide complete code samples
  3. Consider error handling
  4. Explain any relevant limitations
  5. Suggest optimal patterns for their use case
  6. Reference types from the SDK’s type definitions