Skip to main content

MPP payments

The Machine Payments Protocol (MPP) enables crypto-native, per-request payments on the Tempo blockchain. MPP is an additive payment method alongside Stripe — you choose which to use on each request.

How it works

MPP uses an HTTP 402 challenge/response flow:
  1. You send a request to the gateway.
  2. The server returns 402 Payment Required with a challenge containing the price, token, and recipient.
  3. You sign a Tempo transaction matching the challenge.
  4. You retry the request with the signed transaction as a credential in the Authorization header.
  5. The server verifies the payment on-chain and returns the response with a Payment-Receipt header.

Supported networks

NetworkChain IDRPC URLStatus
Tempo Mainnet4217https://rpc.tempo.xyzActive
Tempo Testnet42431https://rpc.moderato.tempo.xyzActive
Set TEMPO_TESTNET=true in your environment to use the testnet during development.

Plugin pricing

Each plugin has a fixed per-request price in USD, settled in pathUSD on Tempo.
PluginPrice per requestDescription
agent$0.05Agent orchestrator
generate-text$0.01LLM text generation
tts$0.03Text-to-speech synthesis
stt$0.02Speech-to-text transcription

Payment credential

After receiving a 402 challenge, build and sign a credential to send with your retry:

Authorization header format

Authorization: Payment <JSON credential>

Credential structure

{
  "scheme": "Payment",
  "transaction": "0x76...",
  "challengeNonce": "a1b2c3d4e5f6..."
}
FieldTypeDescription
schemestringAlways Payment
transactionstringHex-encoded signed Tempo transaction (prefixed with 0x76 type marker)
challengeNoncestringThe nonce value from the 402 challenge (replay protection)

402 challenge structure

When a payment is required, the server responds with:
{
  "error": "payment_required",
  "message": "Payment required for agent. Choose payment method: Stripe or Tempo MPP.",
  "mpp": {
    "scheme": "Payment",
    "amount": "0.05",
    "currency": "0x20c0000000000000000000000000000000000000",
    "recipient": "0xd8fd0e1dce89beaab924ac68098ddb17613db56f",
    "description": "Agent orchestrator request",
    "nonce": "a1b2c3d4e5f6...",
    "expiresAt": 1742472000000
  },
  "stripe": {
    "checkoutUrl": "/api/v1/payments/stripe/create?plugin=agent",
    "amount": "0.05",
    "currency": "usd"
  }
}

Challenge fields

FieldTypeDescription
schemestringAlways Payment
amountstringPrice in USD
currencystringToken contract address (pathUSD)
recipientstringWallet address to pay
descriptionstringHuman-readable description of the charge
noncestringUnique nonce for this challenge (used for replay protection)
expiresAtnumberUnix timestamp (ms) when the challenge expires. Challenges are valid for 5 minutes.

Verification

The server verifies your credential by checking:
  1. The transaction is hex-encoded and starts with the 0x76 type marker.
  2. The recipient address matches the expected recipient.
  3. The token address matches the expected currency (pathUSD).
  4. The amount matches the plugin price (within a 0.0001 tolerance).
  5. The nonce matches the original challenge nonce.
If verification fails, the server returns an error with a description of the mismatch.

Receipt

On success, the server returns:
  • A Payment-Receipt response header containing the transaction hash.
  • The payment.receipt field in the JSON response body.

Client usage

Use mppFetch to handle the full 402 flow automatically:
import { mppFetch } from '@agentbot/sdk';

const result = await mppFetch({
  plugin: 'agent',
  body: { messages: [{ role: 'user', content: 'Hello' }] },
  privateKey: '0xYOUR_PRIVATE_KEY',
  baseUrl: 'https://agentbot.raveculture.xyz',
  testnet: false,
});

if (result.success) {
  console.log(result.data);
  console.log('Receipt:', result.receipt);
}

mppFetch options

OptionTypeRequiredDefaultDescription
pluginstringYesPlugin ID to call
bodyobjectYesRequest body forwarded to the plugin
privateKeystringYesHex-encoded private key for signing Tempo transactions
baseUrlstringNohttps://agentbot.raveculture.xyzAgentbot instance URL
streambooleanNofalseRequest a streaming response
testnetbooleanNofalseUse Tempo testnet instead of mainnet

mppFetch result

FieldTypeDescription
successbooleanWhether the request succeeded
dataobjectResponse body (non-streaming)
streamReadableStreamResponse stream (streaming)
receiptstringPayment receipt hash
errorstringError message on failure

Check MPP support

You can check whether an endpoint supports MPP payments:
import { checkMppSupport } from '@agentbot/sdk';

const { supported } = await checkMppSupport(
  'https://agentbot.raveculture.xyz/api/v1/gateway'
);
The function sends an OPTIONS request and checks for a WWW-Authenticate: Payment header.

Troubleshooting

The plugin may not have a configured price. Only plugins listed in the pricing table above support MPP payments.
  • Ensure the challengeNonce matches the nonce from the 402 response.
  • Verify the transaction amount matches the challenge amount exactly.
  • Check that you are using the correct network (mainnet vs. testnet).
The transaction hex must begin with 0x76 (the Tempo transaction type marker). Ensure your signing implementation includes this prefix.