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 Requiredstatus 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
402status containing aPaymentRequiredJSON body describing the required amount, token, and network - MPP: an HTTP
402with aWWW-Authenticate: MPPheader 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.
// 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
| Property | Value |
|---|---|
| Transaction fee | <$0.001 (typically $0.00025) |
| Finality | <1000ms today; <150ms with Alpenglow upgrade (Q3 2026) |
| Daily transaction volume | 143 million (May 2026) |
| Stablecoin throughput | $2 trillion per quarter |
| Theoretical throughput | 65,000 TPS |
| Sustained throughput | 6,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)
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:
// 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.
Privacy modes
| Mode | Amount | Sender | Receiver | Typical 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:
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.
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.
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.
The recipient sees only that a verified payment arrived, not who sent it, not the source address, not the amount.
ZK proof system
| Property | Value |
|---|---|
| Proof system | Groth16 |
| Proof size | ~0.6 KB |
| On-chain verification time | 1–2 ms |
| Overhead vs. transparent payment | <10 ms end-to-end |
| Trusted setup | None, 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.
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:
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.
Has this agent exceeded its calls-per-window limit? If yes, return RateLimitError.
Does the quoted payment amount exceed perCallLimit? If yes, reject before payment is submitted.
Would this payment push the day's total spend over dailyBudget? If yes, reject. Budget resets at midnight UTC.
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.
// 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
solanaTxLink on Solana Explorer.
Querying the ledger directly
You can query any Fixer Protocol transaction directly via Solana RPC without using our API:
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);