Integration Guide

Integrate prompt mining into your AI service with backend-signed transactions. No user wallets required—your backend handles everything.

How It Works

ProjectZero's prompt mining integration is designed for simplicity and privacy. Your backend signs all transactions and sponsors gas costs, while users never need wallets or blockchain knowledge.

Privacy-First

Full prompts never leave your infrastructure. Only cryptographic hashes are sent to PZERO Gateway and stored on-chain.

Gas Sponsorship

Your backend wallet sponsors all gas costs. Users interact with your service without any blockchain friction.

Backend-Controlled

Your backend signs and submits all transactions. Maintain full control over when and how prompts are minted.

Simple UX

No MetaMask popups, no signature requests. Users just interact with your AI service as usual.

Architecture Flow

Here's how prompt mining integrates into your AI service:

  1. User submits prompt to your AI service (ChatGPT-like interface, API, etc.)
  2. Your backend hashes the prompt locally using keccak256 for privacy
  3. Request authorization from PZERO Gateway with the hash (not the full prompt)
  4. PZERO Gateway returns signature after verifying your API key and quota
  5. Your backend signs and submits the blockchain transaction with your wallet
  6. Prompt is minted on-chain and user receives activity points/rewards

Privacy Guarantee: The PZERO Gateway never sees full prompts—only irreversible hashes. Even ProjectZero cannot determine the original prompt content.

Backend Implementation

The boilerplate provides a complete backend implementation. Here's the core endpoint that mints prompts:

Core Minting Endpoint

routes/prompts.ts
import { ethers } from 'ethers'
import { keccak256 } from 'ethers/lib/utils'
import { apiClient } from './api-client'

app.post('/api/prompts/mint-for-user', async (req, res) => {
  try {
    const { prompt, userId, activityPoints = 25 } = req.body

    // Use your backend wallet as author
    const backendWallet = new ethers.Wallet(process.env.PRIVATE_KEY!)
    const author = backendWallet.address

    // Hash prompt locally (privacy-first)
    const promptHash = keccak256(Buffer.from(prompt))

    // Get authorization from PZERO Gateway
    const authorization = await apiClient.post('/authorize/mint', {
      promptHash,
      author,
      activityPoints,
    }, {
      headers: {
        'x-api-key': process.env.PZERO_API_KEY
      }
    })

    // Connect to blockchain
    const provider = new ethers.JsonRpcProvider(process.env.RPC_URL)
    const wallet = backendWallet.connect(provider)

    const contract = new ethers.Contract(
      process.env.PROMPT_MINER_ADDRESS!,
      ['function mint(bytes32 promptHash, address author, uint256 activityPoints, uint256 nonce, bytes signature)'],
      wallet
    )

    // Submit transaction (you pay gas)
    const tx = await contract.mint(
      promptHash,
      author,
      activityPoints,
      authorization.nonce,
      authorization.signature
    )

    await tx.wait()

    // Store mapping in your database
    await db.userPrompts.create({
      userId,
      promptHash,
      txHash: tx.hash,
      activityPoints,
      createdAt: new Date(),
    })

    res.json({
      success: true,
      txHash: tx.hash,
      promptHash,
      activityPoints
    })
  } catch (error: any) {
    console.error('Mint error:', error)
    res.status(500).json({
      success: false,
      error: error.message
    })
  }
})

Important: Your backend wallet owns all minted prompts on-chain. Maintain a database mapping users to their prompts for internal tracking and reward distribution.

Environment Configuration

Configure your boilerplate with the required environment variables:

Production Environment

.env
# ProjectZero API Configuration
PZERO_API_URL=https://pm-gateway.projectzero.io/v1
PZERO_API_KEY=pzero_live_your_api_key_here

# Blockchain Configuration (Nexera Mainnet)
CHAIN_ID=7358
RPC_URL=https://rpc.nexera.org
PROMPT_MINER_ADDRESS=0x...  # Provided by ProjectZero
ACTIVITY_POINTS_ADDRESS=0x...  # Provided by ProjectZero
DATA_INDEX_ADDRESS=0x...  # Provided by ProjectZero

# Your Backend Wallet (for signing transactions)
PRIVATE_KEY=0x...  # KEEP THIS SECRET!

# Application Settings
NODE_ENV=production
PORT=3001

Getting Your Credentials

  1. Sign in to pm.projectzero.io with OAuth
  2. Navigate to your Dashboard
  3. Create a new API key for your project
  4. Copy the API key and add it to your .env file
  5. Generate a new Ethereum wallet for your backend (or use an existing one)
  6. Fund it with ETH for gas costs (testnet or mainnet depending on environment)

Security Critical: Never commit your .env file or expose your PRIVATE_KEY and PZERO_API_KEY. Add .env to your .gitignore.

Deployment Modes

The boilerplate repository ships with a detailed deployment guide outlining how to promote from local Docker networks to production.

Configuration comparison

Local development defaults to http://pzero-gateway-app:3001/v1, test API keys (pzero_test_...), and Chain ID 72080. Production switches to https://pm-gateway.projectzero.io/v1, pzero_prod_... keys, and Chain ID 7208 with mandatory auth and tighter rate limits.

Docker considerations

Remove the dev-only Docker network prompt-mining-api-gateway_pzero-network before deploying to the public gateway. Use docker-compose -f docker-compose.prod.yml --env-file .env.production up -d --build for official deployments.

.env.production excerpt
PM_NODE_ENV=production
PM_PZERO_API_URL=https://pm-gateway.projectzero.io/v1
PM_PZERO_API_KEY=pzero_prod_your_real_key_here
PM_CHAIN_ID=7208
PM_RPC_URL=https://rpc.nexera.network
PM_REQUIRE_AUTH=true
PM_REQUIRE_AUTH_MINT=true

Need to self-host the gateway? Point PM_PZERO_API_URL to your HTTPS endpoint and keep the application on a single internal Docker network—no shared bridge required.

Testing Your Integration

Verify your integration works correctly before going to production:

1. Verify Configuration

bash
npm run test:config

Expected output:

bash
✓ PZERO_API_KEY is set
✓ PZERO_API_URL is set
✓ RPC_URL is set
✓ PROMPT_MINER_ADDRESS is set
✓ ACTIVITY_POINTS_ADDRESS is set
✓ PRIVATE_KEY is set
✓ All required configuration is valid!

2. Start Development Server

bash
npm run dev

3. Test Minting with cURL

bash
curl -X POST http://localhost:3001/api/prompts/mint-for-user \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "What is quantum computing?",
    "userId": "user_12345",
    "activityPoints": 25
  }'

Expected response:

json
{
  "success": true,
  "txHash": "0xabcdef1234567890...",
  "promptHash": "0x1a2b3c4d5e6f...",
  "activityPoints": 25
}

Database Schema

Store prompt metadata in your database to track user ownership and rewards:

schema.prisma (example)
model UserPrompt {
  id              String   @id @default(cuid())
  userId          String
  promptHash      String   @unique
  txHash          String
  activityPoints  Int
  createdAt       DateTime @default(now())

  @@index([userId])
  @@index([createdAt])
}

This allows you to:

  • Track which prompts belong to which users
  • Display user's prompt history in your dashboard
  • Calculate total rewards earned per user
  • Verify blockchain transactions

Gas Cost Management

As the gas sponsor, you should monitor and optimize gas costs:

Batch Minting (Coming Soon)

Batch multiple prompts into a single transaction to reduce per-prompt gas costs.

Gas Price Monitoring

Monitor gas prices and delay non-urgent mints during high-congestion periods.

Wallet Funding Alerts

Set up alerts when your backend wallet balance drops below a threshold.

For more details, see the Gas Management Guide.

Next Steps

Now that you understand the integration:

API Reference

Complete documentation of all boilerplate endpoints and PZERO Gateway APIs.

View API Docs →

Security Best Practices

Understand the privacy-first architecture and security guarantees.

Learn About Security →

Reward Strategies

Configure activity points and reward mechanisms for your users.

Explore Reward Strategies →

Architecture Deep Dive

Understand how the system works end-to-end.

View Architecture →