Server Path
Lesson 7 of 8
15 min

Dynamic Pricing Strategies

Learning Objectives

  • Understand dynamic price functions
  • Implement tiered pricing based on request context
  • Create user-based pricing
  • Learn when to use dynamic vs static pricing

Why Dynamic Pricing?

Static pricing works for simple APIs, but many applications need flexible pricing:

Use Cases:

Tiered pricing: Standard vs Premium vs Enterprise
User-based pricing: Subscribers pay less than non-subscribers
Content-based pricing: Expensive queries cost more
Volume discounts: Bulk requests get lower per-unit prices
Time-based pricing: Peak hours cost more

Dynamic Price Functions

Instead of a static price string like "$0.001", use a function:

typescript
import { paymentMiddleware } from '@x402/express';

app.use(
  paymentMiddleware(
    {
      'GET /weather': {
        accepts: {
          scheme: 'exact',
          price: (context) => {
            // Access request context
            const tier = context.adapter.getQueryParam?.('tier') ?? 'standard';

            if (tier === 'premium') {
              return '$0.01';  // 1 cent for premium
            }
            return '$0.001';  // 0.1 cent for standard
          },
          network: 'eip155:84532',
          payTo: '0xYourAddress',
        },
      },
    },
    server,
  ),
);
The context parameter gives you access to the HTTP request through context.adapter. You can read query params, headers, and more.

Example 1: Tiered Pricing

Implement three pricing tiers:

typescript
'GET /api/search': {
  accepts: {
    scheme: 'exact',
    price: (context) => {
      const tier = context.adapter.getQueryParam?.('tier') ?? 'standard';

      switch (tier) {
        case 'enterprise':
          return '$0.05';  // 5 cents - unlimited searches
        case 'premium':
          return '$0.01';  // 1 cent - advanced features
        case 'standard':
        default:
          return '$0.001'; // 0.1 cent - basic search
      }
    },
    network: 'eip155:8453',
    payTo: '0xYourAddress',
  },
  description: 'Search API with tiered pricing',
}

Example 2: User-Based Pricing

Charge different prices based on user authentication:

typescript
'POST /api/generate-image': {
  accepts: {
    scheme: 'exact',
    price: async (context) => {
      // Get user ID from auth header
      const authToken = context.adapter.getHeader?.('Authorization');

      if (authToken) {
        const user = await getUserFromToken(authToken);

        if (user.subscription === 'pro') {
          return '$0.001';  // Pro users pay less
        }
      }

      return '$0.005';  // Regular users pay more
    },
    network: 'eip155:8453',
    payTo: '0xYourAddress',
  },
}

Example 3: Content-Based Pricing

Price based on the complexity of the request:

typescript
'POST /api/analyze': {
  accepts: {
    scheme: 'exact',
    price: (context) => {
      // Parse request body size
      const contentLength = context.adapter.getHeader?.('Content-Length');
      const sizeKB = contentLength ? parseInt(contentLength) / 1024 : 0;

      if (sizeKB > 100) {
        return '$0.10';  // Large files cost more
      } else if (sizeKB > 10) {
        return '$0.02';  // Medium files
      }
      return '$0.001';  // Small files
    },
    network: 'eip155:8453',
    payTo: '0xYourAddress',
  },
}
Dynamic pricing runs on every request. Avoid expensive operations (database lookups, external API calls) that could slow down 402 responses.

When to Use Dynamic Pricing

Use Dynamic Pricing When:

Different users need different prices
Price depends on request parameters
You offer multiple service tiers
Cost varies based on resource consumption

Use Static Pricing When:

All users pay the same price
Pricing is simple and fixed
Performance is critical (dynamic pricing adds overhead)

Interactive Playground

typescript
Output

Click "Run Code" to see the output