← Back to Home

API Documentation

Integrate Apocha receipts into your application

Authentication: Most endpoints use x402 payment protocol. Include X-Payment header with your USDC payment signature. For wallet ownership proof, include X-Wallet-Address and X-Wallet-Signature. Security: The wallet that pays the x402 fee must be a participant (payer or seller) in the transaction being minted.
Tax Ready: Receipts include DTIF codes (Digital Token Identifier) for tax reporting. Each attribute is marked as chain-verified or self-reported.
Production Infrastructure: Receipts are minted as compressed NFTs via Metaplex Bubblegum. Metadata is permanently stored on Arweave via Irys. Wallet queries use Helius DAS API.
Reliable Minting: All mints go through a persistent queue with automatic retries (up to 3 attempts). Payment is verified immediately - if minting fails, it retries automatically. Failed mints can be manually retried via admin endpoints.
Data Persistence: All receipts are stored in a persistent SQLite database. This ensures duplicate prevention survives server restarts and provides fast lookups. The on-chain NFT and Arweave metadata remain the immutable source of truth.
Privacy: Payer jurisdiction is detected via IP for tax compliance but is never stored in the on-chain NFT. This data is kept in the private database and only visible to sellers when viewing their receipts. Payers never see location data in their wallet.

Core Endpoints

POST /mint

Mint a verifiable receipt NFT for a transaction. Requires x402 payment (0.1% of transaction, min $0.10, max $5) for transactions over $1. Security: The x402 fee payer must be a participant (payer or seller) in the transaction.

curl -X POST https://api.apocha.cc/mint \
  -H "Content-Type: application/json" \
  -H "X-Payment: <payment_signature>" \
  -H "X-Wallet-Address: <your_wallet>" \
  -H "X-Wallet-Signature: <ownership_proof>" \
  -d '{
    "tx_signature": "5KtP...abc123",
    "service_type": "API Access",
    "transaction_type": "sale",
    "invoice_id": "INV-2026-001"
  }'

# Response
{
  "success": true,
  "receipt_id": "766A00234C47",
  "metadata_uri": "https://gateway.irys.xyz/...",
  "mint_signature": "AkJ5EWBt5UC...",
  "asset_name": "USDC",
  "dtif_code": "488V99169"
}

# Note: Wallet addresses and amount are fetched from blockchain
# You must be the payer or seller to mint a receipt
GET /verify/{tx_signature}

Verify a Solana transaction and get payment details. Free, no payment required.

curl https://api.apocha.cc/verify/5KtP...abc123

# Response
{
  "success": true,
  "transaction": {
    "amount": 10.00,
    "token": "USDC",
    "sender": "7uS8Vp...",
    "receiver": "8hTmUL...",
    "status": "settled"
  }
}
GET /calculate/{tx_signature}?country=XX

Calculate local currency value for a transaction. Free utility - uses Xe for historical exchange rates. Supports 40+ countries.

curl https://api.apocha.cc/calculate/5KtP...abc?country=CA

# Response
{
  "success": true,
  "usd_amount": 100.00,
  "local_currency": "CAD",
  "local_amount": 136.50,
  "exchange_rate": 1.365,
  "rate_date": "2026-01-15",
  "rate_source": "Xe"
}

# Supported countries: US, GB, EU, DE, FR, CA, AU, JP, SG, CH, AE,
# NL, ES, IT, BR, MX, IN, KR, HK, CN, NZ, SE, NO, DK, PL, ZA,
# TH, ID, MY, PH, VN, TR, RU, IL, NG, AR, CL, CO, PE
GET /receipt/{receipt_id}

Lookup a receipt by its ID.

curl https://api.apocha.cc/receipt/766A00234C47
GET /receipt/{receipt_id}/metadata.json

Get the raw JSON metadata for a receipt (Arweave-compatible format).

curl https://api.apocha.cc/receipt/766A00234C47/metadata.json
GET /receipt/{receipt_id}/image.png

Get the generated receipt image (PNG format).

curl https://api.apocha.cc/receipt/766A00234C47/image.png -o receipt.png
GET /mint/status/{receipt_id}

Check the mint status of a receipt. Useful for polling after submitting a mint request.

curl https://api.apocha.cc/mint/status/766A00234C47

# Response (pending)
{
  "success": true,
  "receipt_id": "766A00234C47",
  "mint_status": "pending",
  "attempts": 1,
  "last_error": null
}

# Response (completed)
{
  "success": true,
  "receipt_id": "766A00234C47",
  "mint_status": "completed",
  "metadata_uri": "https://gateway.irys.xyz/..."
}
GET /wallet/{address}/receipts?counterparty={wallet}

Get USDC transfers between two wallets from the blockchain. The counterparty parameter is required - specify the other wallet you transacted with. Returns transfers categorized by sent/received.

curl https://api.apocha.cc/wallet/7uS8Vp.../receipts?counterparty=8hTmUL...

# Required parameter:
#   counterparty - The wallet address you transacted with
#
# Optional parameters:
#   period_start - ISO date (e.g., 2026-01-01)
#   period_end   - ISO date (e.g., 2026-01-31)

# Response
{
  "wallet": "7uS8Vp...",
  "counterparty": "8hTmUL...",
  "sent": {
    "count": 3,
    "total_usdc": 150.00,
    "transfers": [...]
  },
  "received": {
    "count": 2,
    "total_usdc": 75.00,
    "transfers": [...]
  }
}
GET /wallet/{address}/export?country=XX&format=csv

Export all receipts for a wallet in CSV or JSON format with local currency values.

curl https://api.apocha.cc/wallet/7uS8Vp.../export?country=US&format=csv

Statement Endpoint (AI Agents)

For AI Agents: The /statement endpoint lets you batch multiple transactions into ONE statement NFT, or scan a wallet for a time period. Returns JSON + CSV with aggregates.
POST /statement

Create a statement NFT containing multiple transactions. Two modes: explicit transaction list OR wallet scan by date range. Pricing is tiered by transaction count. Security: The x402 fee payer must match the wallet_address in the request.

# Mode 1: Explicit transaction list
curl -X POST https://api.apocha.cc/statement \
  -H "Content-Type: application/json" \
  -H "X-Payment: <payment_signature>" \
  -d '{
    "wallet_address": "7uS8Vp...",
    "transactions": ["sig1...", "sig2...", "sig3..."],
    "output_formats": ["json", "csv"]
  }'

# Mode 2: Wallet scan by date range
curl -X POST https://api.apocha.cc/statement \
  -H "Content-Type: application/json" \
  -H "X-Payment: <payment_signature>" \
  -d '{
    "wallet_address": "7uS8Vp...",
    "period_start": "2026-01-01T00:00:00Z",
    "period_end": "2026-01-31T23:59:59Z",
    "output_formats": ["json", "csv"]
  }'

# Response
{
  "success": true,
  "statement_id": "STMT1A2B3C4D",
  "nft_mint": "AkJ5EWBt...",
  "metadata_uri": "https://gateway.irys.xyz/...",
  "summary": {
    "tx_count": 15,
    "total_usd": 1420.50,
    "period_start": "2026-01-01",
    "period_end": "2026-01-31",
    "by_token": { "USDC": 1420.50 },
    "by_role": { "as_payer": 500.00, "as_seller": 920.50 }
  },
  "transactions": [...],
  "csv_url": "data:text/csv;base64,..."
}

# Pricing (tiered by transaction count):
#   1-10 transactions:  $1 USDC
#   11-50 transactions: $3 USDC
#   51+ transactions:   $5 USDC

Registration

POST /register

Register a seller wallet for automatic receipt generation.

curl -X POST https://api.apocha.cc/register \
  -H "Content-Type: application/json" \
  -d '{
    "wallet_address": "8hTmUL...",
    "business_name": "My API Service",
    "country": "US",
    "service_type": "SaaS"
  }'

Integration Flows

Two Customer Types:

Flow 1: Human - Single Receipt (Frontend)

POST /mint - Stamp a Transaction

Human user connects wallet, signs message to prove ownership, pays via x402 if required.

# REQUEST 1: Initial request with wallet signature
POST /mint
Content-Type: application/json
X-Wallet-Address: 7uS8VpXjrNDsXCD93R36BoRNj2upDNE1Qy1a5yjXnGxq
X-Wallet-Signature: base58_signature_of_"Apocha:5KtP...abc123"

{
  "tx_signature": "5KtP...abc123",
  "service_type": "Purchase"
}

# RESPONSE 1: 402 Payment Required (tx > $1)
{
  "error": "Payment Required",
  "message": "Receipt minting requires $0.10 USDC",
  "transaction_amount": 25.00,
  "paymentRequirements": {
    "x402Version": 1,
    "accepts": [{
      "scheme": "exact",
      "network": "solana-mainnet",
      "asset": "USDC",
      "payTo": "8hTmULLrTpXJxpebL246N4aCo4cqxHTpTrKJyRxeDdWT",
      "maxAmount": "100000"
    }]
  }
}

# STEP: User approves payment in wallet UI

# REQUEST 2: Retry with payment
POST /mint
Content-Type: application/json
X-Wallet-Address: 7uS8VpXjrNDsXCD93R36BoRNj2upDNE1Qy1a5yjXnGxq
X-Wallet-Signature: base58_signature_of_"Apocha:5KtP...abc123"
X-Payment: 3H3FVWmWyg357mRW...payment_tx_signature

{
  "tx_signature": "5KtP...abc123",
  "service_type": "Purchase"
}

# RESPONSE 2: 200 OK
{
  "success": true,
  "receipt_id": "766A00234C47",
  "metadata_uri": "https://gateway.irys.xyz/...",
  "message": "Receipt minted successfully"
}

# Note: Transactions under $1 are FREE (no payment step)

Flow 2: AI Agent - Batch Statement (API)

POST /statement - Batch or Wallet Scan

AI agent submits multiple transactions or scans a wallet for a period. Gets ONE statement NFT + JSON/CSV with aggregates.

# REQUEST 1: Initial statement request (no payment)
POST /statement
Content-Type: application/json

{
  "wallet_address": "7uS8VpXjrNDsXCD93R36BoRNj2upDNE1Qy1a5yjXnGxq",
  "period_start": "2026-01-01T00:00:00Z",
  "period_end": "2026-01-31T23:59:59Z",
  "output_formats": ["json", "csv"]
}

# RESPONSE 1: 402 Payment Required
{
  "error": "Payment Required",
  "message": "Statement requires $3.00 USDC for 25 transactions",
  "tx_count": 25,
  "pricing_tier": "$3.00",
  "paymentRequirements": {
    "x402Version": 1,
    "accepts": [{
      "scheme": "exact",
      "network": "solana-mainnet",
      "asset": "USDC",
      "payTo": "8hTmULLrTpXJxpebL246N4aCo4cqxHTpTrKJyRxeDdWT",
      "maxAmount": "3000000"
    }]
  }
}

# STEP: Agent sends $3 USDC to payTo address

# REQUEST 2: Retry with payment proof
POST /statement
Content-Type: application/json
X-Payment: 4DTSMAapjSX6aW45...payment_tx_signature

{
  "wallet_address": "7uS8VpXjrNDsXCD93R36BoRNj2upDNE1Qy1a5yjXnGxq",
  "period_start": "2026-01-01T00:00:00Z",
  "period_end": "2026-01-31T23:59:59Z",
  "output_formats": ["json", "csv"]
}

# RESPONSE 2: 200 OK - Statement created
{
  "success": true,
  "statement_id": "STMT1A2B3C4D",
  "nft_mint": "AkJ5EWBt5UC...",
  "metadata_uri": "https://gateway.irys.xyz/...",
  "summary": {
    "tx_count": 25,
    "total_usd": 1420.50,
    "by_token": { "USDC": 1420.50 },
    "by_role": { "as_payer": 500.00, "as_seller": 920.50 }
  },
  "transactions": [...],
  "csv_url": "data:text/csv;base64,..."
}

Flow Summary

INFO Quick Reference
┌─────────────────────────────────────────────────────────────────┐
│                    APOCHA ENDPOINTS                             │
├─────────────────────────────────────────────────────────────────┤
│ Use Case        │ Endpoint    │ Payment         │ Output        │
├─────────────────────────────────────────────────────────────────┤
│ Human (single)  │ /mint       │ 0.1% (max $5)   │ 1 Receipt NFT │
│ AI (batch)      │ /statement  │ $1-$3-$5 tiered │ 1 Statement   │
│                 │             │                 │ NFT + JSON/CSV│
├─────────────────────────────────────────────────────────────────┤
│ Free tier: Transactions under $1 USDC = no payment required     │
│ Statement pricing: 1-10 tx=$1, 11-50 tx=$3, 51+ tx=$5           │
│ Security: Wallet must be payer OR seller of the transaction     │
└─────────────────────────────────────────────────────────────────┘

# Headers Reference:
# X-Payment: Payment transaction signature (x402 payment proof)
# X-Wallet-Address: Your wallet public key
# X-Wallet-Signature: Signature of "Apocha:{tx_signature}"

Error Responses

ERROR Common Error Formats

All errors follow a consistent format with success=false.

# 402 - Payment Required
{
  "error": "Payment Required",
  "message": "Receipt minting requires $0.10 USDC",
  "free_tier": "Transactions under $1.0 are free",
  "transaction_amount": 25.00,
  "paymentRequirements": { ... }
}

# 400 - Bad Request
{
  "success": false,
  "error": "Transaction verification failed: not found",
  "status_code": 400
}

# 403 - Forbidden (wallet not involved in tx)
{
  "success": false,
  "error": "Payment sender (7uS8Vp...) is not involved in this transaction",
  "status_code": 403
}

# 409 - Duplicate Receipt
{
  "success": true,
  "receipt_id": "766A00234C47",
  "message": "Receipt already exists for this transaction"
}

# 429 - Rate Limited
{
  "error": "Rate limit exceeded. Try again later."
}

Tech Stack

Infrastructure:
Data Sources: