Dexter
Dexter
Docs

Dynamic Pricing

Dynamic pricing lets you charge based on what the buyer is actually asking the endpoint to do.

Best Fit

Use dynamic pricing when cost scales with:

  • characters
  • bytes
  • records
  • image size
  • any other measurable unit

Example

import express from 'express';
import { createDynamicPricing, createX402Server } from '@dexterai/x402/server';
 
const app = express();
const server = createX402Server({
  payTo: 'YourSolanaAddress...',
  network: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
  facilitatorUrl: 'https://x402.dexter.cash',
});
 
const pricing = createDynamicPricing({
  unitSize: 1000,
  ratePerUnit: 0.01,
  minUsd: 0.01,
  maxUsd: 10.0,
});
 
app.use(express.json());
 
app.post('/api/process', async (req, res) => {
  const { text } = req.body;
  const paymentSig = req.headers['payment-signature'];
 
  if (!paymentSig) {
    const quote = pricing.calculate(text);
    const requirements = await server.buildRequirements({
      amountAtomic: quote.amountAtomic,
      resourceUrl: req.originalUrl,
    });
 
    res.setHeader('PAYMENT-REQUIRED', server.encodeRequirements(requirements));
    res.setHeader('X-Quote-Hash', quote.quoteHash);
    return res.status(402).json({ usdAmount: quote.usdAmount });
  }
 
  const quoteHash = req.headers['x-quote-hash'];
  if (!pricing.validateQuote(text, quoteHash)) {
    return res.status(400).json({ error: 'Input changed, re-quote required' });
  }
 
  const result = await server.settlePayment(paymentSig);
  if (!result.success) {
    return res.status(402).json({ error: result.errorReason });
  }
 
  res.json({ processed: text.length });
});

Why The Quote Hash Matters

The quote hash prevents a client from:

  • asking for a cheap quote
  • changing the payload afterward
  • reusing the old quote for a more expensive request

That makes dynamic pricing safer for merchants whose cost model depends on the actual input.

On this page