Skip to main content

Python SDK for the Pinarkive API v2.3.1 - Easy IPFS file management with directory DAG uploads, file renaming, and enhanced API key management. Includes type hints for better IDE support.

Reason this release was yanked:

Deprecated. Please upgrade to 3.0.x – this version uses the deprecated API v2.

Project description

Pinarkive Python SDK

Python client for the Pinarkive API v2.3.1. Easy IPFS file management with directory DAG uploads, file renaming, and enhanced API key management. Includes type hints for better IDE support and Pythonic usage patterns.

Installation

pip install pinarkive-sdk-py

Quick Start

from pinarkive_client import PinarkiveClient

# Initialize with API key
client = PinarkiveClient(api_key="your-api-key-here")

# Upload a file
result = client.upload_file("document.pdf")
print(f"File uploaded: {result.json()['cid']}")

# Generate API key
token = client.generate_token("my-app", {
    "expires_in_days": 30
})
print(f"New API key: {token.json()['token']}")

Authentication

The SDK supports two authentication methods:

API Key Authentication (Recommended)

client = PinarkiveClient(api_key="your-api-key-here")

Note: The SDK automatically sends the API key using the Authorization: Bearer header format, not X-API-Key.

JWT Token Authentication

client = PinarkiveClient(token="your-jwt-token-here")

Basic Usage

File Upload

# Upload single file
result = client.upload_file("document.pdf")
response_data = result.json()
print(f"CID: {response_data['cid']}")
print(f"Status: {response_data['status']}")

Directory Upload

# Upload directory from local path
result = client.upload_directory("/path/to/directory")
print(f"Directory CID: {result.json()['cid']}")

List Uploads

# List all uploaded files with pagination
result = client.list_uploads(page=1, limit=20)
response_data = result.json()
print(f"Uploads: {response_data['uploads']}")
print(f"Total: {response_data['pagination']['total']}")

Advanced Features

Directory DAG Upload

Upload entire directory structures as DAG (Directed Acyclic Graph):

# Create project structure
project_files = {
    "src/index.py": "print('Hello World')",
    "src/utils.py": "def utils(): pass",
    "requirements.txt": "requests>=2.31.0",
    "README.md": "# My Project\n\nThis is my project."
}

# Upload as DAG
result = client.upload_directory_dag(project_files, dir_name="my-project")
response_data = result.json()
print(f"DAG CID: {response_data['dagCid']}")
print(f"Files: {response_data['files']}")

Directory Cluster Upload

# Upload using cluster-based approach
files = [
    {"path": "file1.txt", "content": "Content 1"},
    {"path": "file2.txt", "content": "Content 2"}
]

result = client.upload_directory_cluster(files)
print(f"Cluster CID: {result.json()['cid']}")

Upload File to Existing Directory

# Add file to existing directory
result = client.upload_file_to_directory("new-file.txt", "existing-directory-path")
print(f"File added to directory: {result.json()['cid']}")

File Renaming

# Rename an uploaded file
result = client.rename_file("upload-id-here", "new-file-name.pdf")
print(f"File renamed: {result.json()['updated']}")

File Removal

# Remove a file from storage
result = client.remove_file("QmYourCIDHere")
print(f"File removed: {result.json()['success']}")

Pinning Operations

Basic CID Pinning

# Pin with filename
result = client.pin_cid("QmYourCIDHere", "my-file.pdf")
print(f"CID pinned: {result.json()['pinned']}")

# Pin without filename (backend will use default)
result2 = client.pin_cid("QmYourCIDHere")
print(f"CID pinned: {result2.json()['pinned']}")

Pin with Custom Name

result = client.pin_cid_with_name("QmYourCIDHere", "my-important-file")
print(f"CID pinned with name: {result.json()['pinned']}")

API Key Management

Generate API Key

# Basic token generation
token = client.generate_token("my-app")

# Advanced token with options
token = client.generate_token("my-app", {
    "expires_in_days": 30,
    "ip_allowlist": ["192.168.1.1", "10.0.0.1"],
    "permissions": ["upload", "pin"]
})
print(f"New API key: {token.json()['token']}")

List API Keys

tokens = client.list_tokens()
print(f"API Keys: {tokens.json()['tokens']}")

Revoke API Key

result = client.revoke_token("my-app")
print(f"Token revoked: {result.json()['revoked']}")

Type Hints Support

The SDK includes comprehensive type hints for better IDE support:

from typing import Dict, Any, Optional
from pinarkive_client import PinarkiveClient

# Type hints provide better autocomplete and error checking
client = PinarkiveClient(api_key="your-key")

# IDE will show parameter types and return types
def upload_project_files(files: Dict[str, str]) -> Any:
    return client.upload_directory_dag(files, dir_name="project")

# Type hints for options
token_options: Dict[str, Any] = {
    "expires_in_days": 30,
    "ip_allowlist": ["192.168.1.1"]
}
token = client.generate_token("my-app", token_options)

Error Handling

import requests

try:
    result = client.upload_file("document.pdf")
    print("Success:", result.json())
except requests.exceptions.RequestException as e:
    if hasattr(e, 'response') and e.response is not None:
        print(f"API Error: {e.response.status_code}")
        print(f"Response: {e.response.json()}")
    else:
        print(f"Network Error: {e}")

Integration Examples

Django Integration

# views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from pinarkive_client import PinarkiveClient
import json

@csrf_exempt
def upload_file(request):
    if request.method == 'POST':
        client = PinarkiveClient(api_key=settings.PINARKIVE_API_KEY)
        
        uploaded_file = request.FILES['file']
        # Save temporarily
        with open(f'/tmp/{uploaded_file.name}', 'wb+') as destination:
            for chunk in uploaded_file.chunks():
                destination.write(chunk)
        
        try:
            result = client.upload_file(f'/tmp/{uploaded_file.name}')
            return JsonResponse(result.json())
        except Exception as e:
            return JsonResponse({'error': str(e)}, status=500)
    
    return JsonResponse({'error': 'Method not allowed'}, status=405)

Flask Integration

from flask import Flask, request, jsonify
from pinarkive_client import PinarkiveClient
import os

app = Flask(__name__)
client = PinarkiveClient(api_key=os.environ.get('PINARKIVE_API_KEY'))

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return jsonify({'error': 'No file provided'}), 400
    
    file = request.files['file']
    if file.filename == '':
        return jsonify({'error': 'No file selected'}), 400
    
    # Save temporarily
    temp_path = f'/tmp/{file.filename}'
    file.save(temp_path)
    
    try:
        result = client.upload_file(temp_path)
        os.remove(temp_path)  # Clean up
        return jsonify(result.json())
    except Exception as e:
        os.remove(temp_path)  # Clean up on error
        return jsonify({'error': str(e)}), 500

@app.route('/files', methods=['GET'])
def list_files():
    try:
        result = client.list_uploads()
        return jsonify(result.json())
    except Exception as e:
        return jsonify({'error': str(e)}), 500

FastAPI Integration

from fastapi import FastAPI, File, UploadFile, HTTPException
from pinarkive_client import PinarkiveClient
import tempfile
import os

app = FastAPI()
client = PinarkiveClient(api_key=os.environ.get('PINARKIVE_API_KEY'))

@app.post("/upload")
async def upload_file(file: UploadFile = File(...)):
    # Create temporary file
    with tempfile.NamedTemporaryFile(delete=False) as temp_file:
        content = await file.read()
        temp_file.write(content)
        temp_file.flush()
        
        try:
            result = client.upload_file(temp_file.name)
            os.unlink(temp_file.name)  # Clean up
            return result.json()
        except Exception as e:
            os.unlink(temp_file.name)  # Clean up on error
            raise HTTPException(status_code=500, detail=str(e))

@app.get("/files")
async def list_files(page: int = 1, limit: int = 10):
    try:
        result = client.list_uploads(page=page, limit=limit)
        return result.json()
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

API Reference

Constructor

PinarkiveClient(token: Optional[str] = None, api_key: Optional[str] = None, base_url: str = 'https://api.pinarkive.com/api/v2')
  • token: Optional JWT token for authentication
  • api_key: Optional API key for authentication
  • base_url: Base URL for the API (defaults to production)

File Operations

  • uploadFile(file_path: str) - Upload single file
  • uploadDirectory(dir_path: str) - Upload directory recursively (calls uploadFile for each file)
  • uploadDirectoryDAG(files_dict: Dict[str, Any], dir_name: Optional[str] = None) - Upload directory as DAG structure
  • renameFile(upload_id: str, new_name: str) - Rename uploaded file
  • removeFile(cid: str) - Remove file from storage

Pinning Operations

  • pinCid(cid: str, filename: Optional[str] = None) - Pin CID to account with optional filename

User Operations

  • listUploads(page: int = 1, limit: int = 10) - List uploaded files

Token Management

  • generateToken(name: str, options: Optional[Dict[str, Any]] = None) - Generate API key
  • listTokens() - List all API keys
  • revokeToken(name: str) - Revoke API key

Status & Monitoring

  • getStatus(cid: str) - Get file status
  • getAllocations(cid: str) - Get storage allocations

Examples

Complete File Management Workflow

from pinarkive_client import PinarkiveClient

def manage_files():
    client = PinarkiveClient(api_key="your-api-key")
    
    try:
        # 1. Upload a file
        result = client.upload_file("document.pdf")
        upload_data = result.json()
        print(f"Uploaded: {upload_data['cid']}")
        
        # 2. Pin the CID with a custom name
        pin_result = client.pin_cid_with_name(upload_data['cid'], "important-document")
        print(f"Pinned: {pin_result.json()['pinned']}")
        
        # 3. Rename the file
        if 'uploadId' in upload_data:
            rename_result = client.rename_file(upload_data['uploadId'], "my-document.pdf")
            print(f"Renamed: {rename_result.json()['updated']}")
        
        # 4. List all uploads
        uploads = client.list_uploads()
        print(f"All uploads: {uploads.json()['uploads']}")
        
    except Exception as e:
        print(f"Error: {e}")

manage_files()

Directory Upload Workflow

def upload_project():
    client = PinarkiveClient(api_key="your-api-key")
    
    # Create project structure
    project_files = {
        "src/main.py": "print('Hello World')",
        "src/utils.py": "def helper(): pass",
        "requirements.txt": "requests>=2.31.0",
        "README.md": "# My Project\n\nThis is my project."
    }
    
    try:
        result = client.upload_directory_dag(project_files, dir_name="my-project")
        response_data = result.json()
        print(f"Project uploaded: {response_data['dagCid']}")
        print(f"Files: {response_data['files']}")
    except Exception as e:
        print(f"Upload failed: {e}")

upload_project()

Batch File Processing

import os
from pathlib import Path

def upload_directory_contents(directory_path: str):
    client = PinarkiveClient(api_key="your-api-key")
    
    files_dict = {}
    directory = Path(directory_path)
    
    # Recursively collect all files
    for file_path in directory.rglob('*'):
        if file_path.is_file():
            # Get relative path from directory
            relative_path = str(file_path.relative_to(directory))
            
            # Read file content
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            files_dict[relative_path] = content
    
    try:
        result = client.upload_directory_dag(files_dict, dir_name=directory.name)
        print(f"Directory uploaded: {result.json()['dagCid']}")
    except Exception as e:
        print(f"Upload failed: {e}")

# Usage
upload_directory_contents("./my-project")

Publishing Instructions

Publishing to PyPI

This package is published to PyPI using the following process:

# Update version in pyproject.toml
python -m build
twine upload dist/*

Development Build

For testing before publishing:

# Build the package
python -m build

# Upload to TestPyPI for testing
twine upload --repository testpypi dist/*

# Install from TestPyPI to test
pip install --index-url https://test.pypi.org/simple/ pinarkive-sdk-py

Version Management

  • Update version in pyproject.toml
  • Build the package with python -m build
  • Upload to PyPI with twine upload dist/*
  • Tag the release in git: git tag v2.3.1 && git push origin v2.3.1

PyPI Best Practices

  • Use semantic versioning (2.3.1, 2.4.0, etc.)
  • Test on TestPyPI before publishing to production
  • Include comprehensive README and documentation
  • Use proper classifiers in pyproject.toml

Support

For issues or questions:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pinarkive_sdk_py-2.3.1.tar.gz (6.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pinarkive_sdk_py-2.3.1-py3-none-any.whl (6.8 kB view details)

Uploaded Python 3

File details

Details for the file pinarkive_sdk_py-2.3.1.tar.gz.

File metadata

  • Download URL: pinarkive_sdk_py-2.3.1.tar.gz
  • Upload date:
  • Size: 6.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.10

File hashes

Hashes for pinarkive_sdk_py-2.3.1.tar.gz
Algorithm Hash digest
SHA256 e1f91ab035394dfd8642974e381854c7afe5705d3b4906550eed7930ecd455c7
MD5 bd9583e6bc9186a29cd030d58db9756c
BLAKE2b-256 ab72f42dcccc8a7802ce5f70733b2b33a6000c04a249539bb0f6d33336ea48de

See more details on using hashes here.

File details

Details for the file pinarkive_sdk_py-2.3.1-py3-none-any.whl.

File metadata

File hashes

Hashes for pinarkive_sdk_py-2.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 13af5485d2e2133cc737b19bd5550c5229092ef6de7ed03239ccf50f35ae2055
MD5 0e337546617191164b4d151ac4851f7e
BLAKE2b-256 ecc9e320652f63a52ca993512fda7b609590434ad1c040005d48b6113292fa62

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page