GitHub fixerprotocol.org →
Core Concepts

How Fixer Protocol Works

A deeper look at protocol detection, Solana settlement, ZK privacy, spend policies, and multi-agent payment chains, the building blocks behind fixer.pay().

Protocol Detection

In 2025 and 2026, two machine payment protocols became dominant:

  • x402 (Coinbase), a lightweight HTTP-native standard that embeds payment handshakes in request/response cycles using the long-dormant HTTP 402 Payment Required status code. Blockchain-native. USDC-settled. Zero protocol fees.
  • MPP: Machine Payments Protocol, co-authored by Stripe and Tempo and submitted as an IETF Standards Track Internet-Draft. Multi-rail (stablecoins, cards, Lightning). Native session support. Integrated by OpenAI, Anthropic, Google Gemini, fal.ai, Modal, Dune, and 50+ services.

Neither protocol is going away. Fixer Protocol detects which one a service requires, automatically, so you never need to know or care.

How detection works

When your agent calls fixer.pay({ endpoint: "..." }), the gateway makes a probe request to the target service. If the service requires payment, it responds with:

  • x402: an HTTP 402 status containing a PaymentRequired JSON body describing the required amount, token, and network
  • MPP: an HTTP 402 with a WWW-Authenticate: MPP header and a session token URL

The gateway reads the response, identifies the protocol, completes the handshake, and retransmits the original request with payment headers attached. Your agent only ever sees the final 200 OK from the service.

typescript
// You write this:
const result = await fixer.pay({
  endpoint: "https://api.dune.com/api/v1/query/3326266/results",
});

// Fixer Protocol handles this internally:
// → Probe request → 402 with MPP header detected
// → MPP session negotiation with Tempo rails
// → Payment submitted via MPP
// → Solana bridge records on-chain transaction
// → Original API response returned as result.data

Protocol preference

If a service supports both x402 and MPP, Fixer Protocol selects x402 by default: it has lower overhead and is fully on-chain. You can override this per-agent or per-call via the dashboard settings.

Solana Settlement

Every transaction processed by Fixer Protocol, whether the underlying protocol is x402 or MPP, is recorded on Solana mainnet via the fixerprotocol.sol on-chain program.

Why Solana

PropertyValue
Transaction fee<$0.001 (typically $0.00025)
Finality<1000ms today; <150ms with Alpenglow upgrade (Q3 2026)
Daily transaction volume143 million (May 2026)
Stablecoin throughput$2 trillion per quarter
Theoretical throughput65,000 TPS
Sustained throughput6,284 TPS

Solana's fee-per-account-state model means fees scale by contention on specific state, not globally, making it ideal for parallel agent workloads where many agents transact independently, each operating on their own PDA.

On-chain record contents

Each on-chain record written by fixerprotocol.sol contains:

  • Agent wallet address (PDA)
  • Counterparty address (service endpoint hash)
  • USDC amount
  • Protocol used (x402 or MPP)
  • Timestamp
  • Policy check result (pass / violation code)
  • Parent transaction hash (for multi-agent chains)
ℹ️
Finance teams can audit every agent payment directly via Solana Explorer or by querying via Solana RPC, no third-party reporting layer or Fixer Protocol dashboard access required.

Agent Wallets

Every agent provisioned through Fixer Protocol receives a Solana Program Derived Address (PDA) scoped to its agentId. This wallet holds USDC and is the settlement source for all payments.

PDA derivation

The wallet address is derived deterministically from the agentId and the fixerprotocol.sol program ID:

typescript
// Address derivation (handled by the SDK/gateway)
const [walletPDA] = PublicKey.findProgramAddressSync(
  [Buffer.from("agent"), Buffer.from(agentId)],
  FIXER_PROGRAM_ID,
);

This means the same agentId always maps to the same Solana address, across SDK versions, across restarts, and across environments. The wallet is non-custodial: Fixer Protocol cannot move funds without a valid signed instruction from the registered agent keypair.

Funding options

  • Direct USDC transfer: send SPL USDC to the wallet's Solana address
  • Dashboard top-up: card payment via app.fixerprotocol.org (converts to on-chain USDC)
  • Programmatic: call fixer.wallet.fund() from your own Solana wallet

ZK Privacy

By default, Fixer Protocol settles every transaction transparently on Solana, amount, sender, and counterparty are all visible. For agents where payment confidentiality is required, Fixer Protocol provides a ZK privacy mode that can be toggled per-call or set as the default for an entire agent.

💡
Transparent by default, private on demand. Most agent workloads benefit from transparency for auditability. Enable privacy only for the calls that require it, competitive intelligence queries, proprietary service usage, or transactions subject to disclosure restrictions.

Privacy modes

ModeAmountSenderReceiverTypical Use
Transparent (default) Public Public Public Audit, compliance, team dashboards
confidential_amount Hidden Public Public Budget privacy, competitive rates
full Hidden Hidden Hidden Maximum confidentiality
full + disclosureKey Hidden Hidden Hidden + disclosure key Regulated environments

Amount privacy, Token-2022 Confidential Transfers

USDC amounts are encrypted using ElGamal encryption before being committed on-chain. A zero-knowledge range proof proves the encrypted amount is valid and non-negative, without revealing the number. Solana's native Token-2022 program verifies these proofs directly; no custom circuit is required for amount hiding.

Sender/Receiver privacy, Commitment + Nullifier Scheme

The approach is structurally identical to Zcash's shielded pool:

1
Deposit

The agent deposits funds into the Fixer Protocol shielded pool and receives a private note: a cryptographic commitment stored off-chain. The deposit transaction is public; the link between depositor and future spender is not.

2
Prove

To pay a service, the agent generates a Groth16 zero-knowledge proof that it holds a valid, unspent commitment, without revealing which deposit it corresponds to.

3
Settle

The fixerprotocol.sol on-chain program verifies the proof, records a nullifier hash (preventing double-spend without revealing identity), and releases funds to the recipient.

4
Receive

The recipient sees only that a verified payment arrived, not who sent it, not the source address, not the amount.

ZK proof system

PropertyValue
Proof systemGroth16
Proof size~0.6 KB
On-chain verification time1–2 ms
Overhead vs. transparent payment<10 ms end-to-end
Trusted setupNone, multi-party ceremony, published on-chain

Groth16 was chosen over zk-STARKs: STARK proofs are 100–200× larger (~69 KB vs ~0.6 KB), making them prohibitively expensive for high-frequency micropayments on Solana.

What remains on-chain in full private mode

Even in full privacy mode, the Solana ledger records:

  • A nullifier hash: prevents double-spend; reveals nothing about the payment
  • A Groth16 validity proof: confirms the proof was verified by the on-chain program
  • Timestamp and Fixer Protocol program ID

What is not on-chain: amount, sender address, receiver address, or any identifying information about the service paid.

Selective disclosure

In regulated environments, agents can attach a disclosure key to a private payment. This generates a secondary ZK proof, a viewing credential, that opens the transaction details to a specific public key (e.g., a compliance officer) without making those details public.

typescript
const result = await fixer.pay({
  endpoint: "https://api.service.com/resource",
  privacy: {
    mode: "full",
    disclosureKey: complianceOfficerPublicKey,
  },
});

// Send result.disclosureProof to the compliance officer
// They can decrypt with their private key — nobody else can

Spend Policies

Spend policies are enforced at the gateway layer, before any payment is submitted. A call that would breach the daily budget is rejected immediately, not after funds are deducted. Policy violations are logged on-chain as anonymised records.

Policy enforcement order

For every fixer.pay() call, the gateway checks in this order:

1
Domain check

Is the target endpoint on the allowedDomains list (if non-empty)? Is it on the blockedDomains list? If blocked, the call is rejected immediately with a PolicyViolationError.

2
Rate limit check

Has this agent exceeded its calls-per-window limit? If yes, return RateLimitError.

3
Per-call limit check

Does the quoted payment amount exceed perCallLimit? If yes, reject before payment is submitted.

4
Daily budget check

Would this payment push the day's total spend over dailyBudget? If yes, reject. Budget resets at midnight UTC.

5
Payment proceeds

All checks passed, the gateway routes the payment.

Policies in ZK private mode

Budget caps, allowlists, and rate limits all remain active in private mode. They are enforced before the ZK proof is generated, the policy engine sees the plaintext; the chain does not. Policy violation events are logged as anonymised on-chain records with no payment details disclosed.

Multi-Agent Payments

When an orchestrating agent delegates to sub-agents and those sub-agents incur costs, the full payment chain is fully traceable on-chain. Each sub-agent payment includes a parentTxHash linking it to the orchestrator's invoking transaction.

typescript
// Orchestrator agent
const fixer = new FixerProtocol({
  agentId: "orchestrator-agent",
  apiKey: process.env.FIXER_API_KEY!,
});

// Invoke a research sub-agent with a budget cap
const subResult = await fixer.request("POST", "/v1/agents/invoke", {
  agentEndpoint: "https://research-agent.yourplatform.com/run",
  task: { query: "Summarise Q1 2026 Solana TVL trends" },
  budget: { usdc: 0.50 }, // max spend for this sub-agent run
});

// Sub-agent payments are linked to orchestrator's tx on-chain
console.log(subResult.paymentChain); // Array of Solana tx hashes
console.log(subResult.totalSpent);   // { usdc: 0.018 }

On-chain linkage

The on-chain ledger stores a parentTxHash on every sub-agent payment. This means a finance team can reconstruct the full payment graph for any orchestrator run, who paid whom, for what, and in what order, directly from Solana, without any off-chain database.

On-Chain Ledger

The Fixer Protocol Solana program (fixerprotocol.sol) handles:

  • Agent wallet registry: PDA per agentId
  • Transaction ledger: payment metadata (protocol, amount, counterparty, timestamp)
  • Policy enforcement: on-chain budget checks for high-value transactions
  • Multi-agent routing: Agent A → Agent B, fully traceable
  • USDC token management: SPL Token program integration
  • ZK verifier (Phase 4), Groth16 pairing checks for shielded transactions
ℹ️
The dashboard is read-only. The app.fixerprotocol.org dashboard reads directly from Solana, there is no separate database. What you see is what is on-chain. You can verify any transaction by looking up its solanaTxLink on Solana Explorer.

Querying the ledger directly

You can query any Fixer Protocol transaction directly via Solana RPC without using our API:

typescript
import { Connection } from "@solana/web3.js";

const connection = new Connection("https://api.mainnet-beta.solana.com");

// Fetch a Fixer Protocol transaction directly from Solana
const tx = await connection.getTransaction("5xGh9KmBv...", {
  commitment: "confirmed",
  maxSupportedTransactionVersion: 0,
});

// The transaction's log messages include Fixer Protocol program data
console.log(tx?.meta?.logMessages);