Consuming an MPP API
Learn how to call an AI agent through the MPP Gateway, handle the HTTP 402 challenge, and construct a Solana payment transaction programmatically.
The HTTP 402 Flow
Unlike traditional APIs where you attach a static Authorization: Bearer <token> header, MPP requires a cryptographic proof of payment for every single request.
The lifecycle of a request looks like this:
- Initial Request: You send a standard HTTP request to the MPP Gateway without any authentication.
- The Challenge: The Gateway responds with
402 Payment Requiredand provides the payment details (amount, provider wallet, platform fee wallet) in theWWW-Authenticateheader. - Payment: Your application uses
@solana/web3.jsto construct a transaction sending funds to the provider and platform, and signs it with your private key. - Retry: You resend the exact same HTTP request, but this time you attach the transaction signature in the headers.
- Success: The Gateway verifies the payment on-chain and proxies your request to the underlying AI model.
TypeScript Implementation
Below is a complete, working example of how to consume an MPP endpoint using Node.js and the official @solana/web3.js SDK.
import { Connection, Keypair, SystemProgram, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
import fetch from "node-fetch";
// 1. Setup your Solana Wallet (Consumer)
const privateKey = new Uint8Array([/* YOUR PRIVATE KEY ARRAY */]);
const consumerWallet = Keypair.fromSecretKey(privateKey);
const connection = new Connection("https://api.mainnet-beta.solana.com", "confirmed");
async function callAIAgent(prompt: string) {
const url = "https://api.mpp.dev/v1/gateway/defi-sentiment";
const body = JSON.stringify({ prompt });
// 2. Initial Request (Will fail with 402)
console.log("Sending initial request...");
let res = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body
});
if (res.status === 402) {
// 3. Extract the Challenge
const challenge = res.headers.get("WWW-Authenticate");
console.log("Received 402 Challenge:", challenge);
// Parse the challenge string (simplified for example)
// Expected: Payment address="ProviderPubKey", amount="0.5", fee_wallet="PlatformPubKey", fee_percent="2%"
const providerAddr = challenge.match(/address="([^"]+)"/)[1];
const amountStr = challenge.match(/amount="([^"]+)"/)[1];
const feeWalletAddr = challenge.match(/fee_wallet="([^"]+)"/)[1];
const totalAmount = parseFloat(amountStr) * 1e9; // Convert SOL to Lamports
const platformFee = totalAmount * 0.02; // 2%
const providerAmount = totalAmount - platformFee;
// 4. Construct the P2P Transaction
console.log("Building Solana Transaction...");
const transaction = new Transaction().add(
// Transfer to Provider
SystemProgram.transfer({
fromPubkey: consumerWallet.publicKey,
toPubkey: new PublicKey(providerAddr),
lamports: providerAmount,
}),
// Transfer 2% Fee to Platform
SystemProgram.transfer({
fromPubkey: consumerWallet.publicKey,
toPubkey: new PublicKey(feeWalletAddr),
lamports: platformFee,
})
);
// 5. Sign and Send
const signature = await sendAndConfirmTransaction(connection, transaction, [consumerWallet]);
console.log("Payment Confirmed! Signature:", signature);
// 6. Retry Request with Signature
res = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Payment signature=${signature}`
},
body
});
}
// 7. Get final AI response
const data = await res.json();
console.log("AI Response:", data);
}
callAIAgent("Is Solana trending bullish today?");Security Best Practice
For production applications, do not hardcode private keys in your source code. Use environment variables or a secure key management system (KMS). If building a web application, use a wallet adapter extension (like Phantom) to let users sign transactions manually.
cURL Example
If you have already executed a transaction and have a valid signature, you can test the API directly from your terminal:
curl -X POST https://api.mpp.dev/v1/gateway/defi-sentiment \
-H "Content-Type: application/json" \
-H "Authorization: Payment signature=5gP...your_signature_here...3bQ" \
-d '{"prompt": "Analyze market trends"}'Python Implementation
Here is an equivalent example for Python developers using the solana package.
import requests
from solana.rpc.api import Client
from solders.keypair import Keypair
from solders.pubkey import Pubkey
from solders.system_program import TransferParams, transfer
from solana.transaction import Transaction
import re
# Setup Wallet
keypair = Keypair.from_bytes(b'\x00' * 64) # Replace with real private key
solana_client = Client("https://api.mainnet-beta.solana.com")
url = "https://api.mpp.dev/v1/gateway/defi-sentiment"
# Initial Request (Expect 402)
response = requests.post(url, json={"prompt": "Is Solana trending bullish today?"})
if response.status_code == 402:
challenge = response.headers.get("WWW-Authenticate")
# Parse challenge (simplified)
provider_addr = re.search(r'address="([^"]+)"', challenge).group(1)
amount_str = re.search(r'amount="([^"]+)"', challenge).group(1)
fee_wallet = re.search(r'fee_wallet="([^"]+)"', challenge).group(1)
total_lamports = int(float(amount_str) * 1e9)
fee_lamports = int(total_lamports * 0.02)
provider_lamports = total_lamports - fee_lamports
# Build Transaction
txn = Transaction()
txn.add(transfer(TransferParams(from_pubkey=keypair.pubkey(), to_pubkey=Pubkey.from_string(provider_addr), lamports=provider_lamports)))
txn.add(transfer(TransferParams(from_pubkey=keypair.pubkey(), to_pubkey=Pubkey.from_string(fee_wallet), lamports=fee_lamports)))
# Sign and Send
result = solana_client.send_transaction(txn, keypair)
signature = result.value
print("Signature:", signature)
# Retry Request
headers = {"Authorization": f"Payment signature={signature}"}
final_response = requests.post(url, json={"prompt": "Is Solana trending bullish today?"}, headers=headers)
print("AI Response:", final_response.json())Note: Transaction signatures can only be used once per request to prevent replay attacks. The MPP Gateway tracks signatures and enforces idempotency.
Built for the machine economy by MPP Layer.
