Available Now

Hanzo Storage

Decentralized storage, simple API

Store NFT metadata, user content, and application data on IPFS, Arweave, or Filecoin. A simple API abstracts the complexity of decentralized storage.

Global CDN

Content served from edge locations worldwide. Sub-100ms retrieval.

IPFS Pinning

Pin content to IPFS with redundant storage across multiple providers.

Permanent Storage

Arweave integration for truly permanent, immutable storage.

Instant Uploads

Upload files and get a content-addressed URL immediately.

Back to Web3 Overview

Get Your API Key

Start building in under 5 minutes

99.999%
Uptime
<50ms
Latency
100+
Chains

No credit card required. Free tier includes 300M compute units/month.

Trusted by developers building:

DeFiNFTsPaymentsGamingAI Agents

Key Capabilities

Everything you need, nothing you don't.

Global CDN

Content served from edge locations worldwide. Sub-100ms retrieval.

IPFS Pinning

Pin content to IPFS with redundant storage across multiple providers.

Permanent Storage

Arweave integration for truly permanent, immutable storage.

Instant Uploads

Upload files and get a content-addressed URL immediately.

NFT Metadata

Optimized for NFT metadata with ERC-721 and ERC-1155 standards.

JSON Storage

Store and query JSON documents with automatic indexing.

Versioning

Track content versions with IPNS for mutable references.

Access Control

Encrypted storage with token-gated access controls.

Gateway URLs

Get HTTP gateway URLs for easy integration with any application.

Simple to Integrate

Get started with just a few lines of code. SDKs for every language.

NFTMetadata.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

/// @title NFTMetadata - NFT with IPFS/Arweave metadata storage
/// @notice ERC-721 with decentralized storage integration
contract NFTMetadata is ERC721, Ownable {
    // Base URI for IPFS gateway
    string public baseURI;

    // Token URI overrides for individual tokens
    mapping(uint256 => string) private _tokenURIs;

    // Storage provider tracking
    enum StorageProvider { IPFS, Arweave, Filecoin }
    mapping(uint256 => StorageProvider) public tokenStorageProvider;

    event MetadataUpdated(
        uint256 indexed tokenId,
        string uri,
        StorageProvider indexed provider
    );

    event BaseURIUpdated(string oldURI, string newURI);

    constructor(
        string memory name,
        string memory symbol,
        string memory _baseURI
    ) ERC721(name, symbol) Ownable(msg.sender) {
        baseURI = _baseURI;
    }

    // Mint with IPFS metadata
    function mintWithIPFS(
        address to,
        uint256 tokenId,
        string calldata ipfsCID
    ) external onlyOwner {
        _safeMint(to, tokenId);
        _tokenURIs[tokenId] = string(abi.encodePacked("ipfs://", ipfsCID));
        tokenStorageProvider[tokenId] = StorageProvider.IPFS;
        emit MetadataUpdated(tokenId, _tokenURIs[tokenId], StorageProvider.IPFS);
    }

    // Mint with Arweave metadata (permanent)
    function mintWithArweave(
        address to,
        uint256 tokenId,
        string calldata arweaveTxId
    ) external onlyOwner {
        _safeMint(to, tokenId);
        _tokenURIs[tokenId] = string(abi.encodePacked("ar://", arweaveTxId));
        tokenStorageProvider[tokenId] = StorageProvider.Arweave;
        emit MetadataUpdated(tokenId, _tokenURIs[tokenId], StorageProvider.Arweave);
    }

    // Update metadata for dynamic NFTs
    function updateMetadata(
        uint256 tokenId,
        string calldata newURI,
        StorageProvider provider
    ) external onlyOwner {
        require(_ownerOf(tokenId) != address(0), "Token does not exist");
        _tokenURIs[tokenId] = newURI;
        tokenStorageProvider[tokenId] = provider;
        emit MetadataUpdated(tokenId, newURI, provider);
    }

    // Override tokenURI to support individual URIs
    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        require(_ownerOf(tokenId) != address(0), "Token does not exist");
        string memory _tokenURI = _tokenURIs[tokenId];
        if (bytes(_tokenURI).length > 0) {
            return _tokenURI;
        }
        return string(abi.encodePacked(baseURI, Strings.toString(tokenId)));
    }

    // Update base URI
    function setBaseURI(string calldata newBaseURI) external onlyOwner {
        emit BaseURIUpdated(baseURI, newBaseURI);
        baseURI = newBaseURI;
    }
}

Built For

NFT Collections

Store metadata and images for NFT collections with guaranteed availability.

dApp Assets

Host frontend assets, documentation, and user-generated content.

Data Backup

Permanent backup of important documents and records on Arweave.

Social Platforms

Store user posts, media, and profiles with decentralized ownership.

Start Building with Hanzo Storage

Get your free API key and ship your first request in under 5 minutes. No credit card required.

Open source

License: AGPL-3.0hanzoai/storage

Forked from MinIO (AGPL-3.0). We track upstream and contribute fixes back where possible.

Get Hanzo Storage

S3-compatible object storage