> Feedback: If these docs are stale, missing, or confusing, post sanitized feedback to `https://docs.tempo.xyz/api/feedback` with `source: "mcp"`, a short `message`, and any relevant `toolName`, `relatedResource`, or `client`.
# Accept one-time payments

Build a payment-gated API that charges $0.01 per request using `mppx`. The server returns a random photo from [Picsum](https://picsum.photos) behind a paywall.

## Server setup

::::steps

### Install dependencies

:::code-group

```bash [npm]
npm install mppx viem
```

```bash [pnpm]
pnpm add mppx viem
```

```bash [bun]
bun add mppx viem
```

:::

### Set up `Mppx` instance

Set up an `Mppx` instance with the `tempo` method.

* `recipient` is the address where you receive payments.
* `currency` is the token address for payments (in this case, `pathUSD`).

```ts
import { Mppx, tempo } from 'mppx/server'

const mppx = Mppx.create({
  methods: [tempo({
    currency: '0x20c0000000000000000000000000000000000000',
    recipient: '0xa726a1CD723409074DF9108A2187cfA19899aCF8',
  })],
})
```

### Add a payment-gated route

Add payment verification using `mppx.charge` as route middleware. The handler only runs after payment is verified.

:::code-group

```ts [Next.js]
import { Mppx, tempo } from 'mppx/nextjs'

const mppx = Mppx.create({
  methods: [tempo({
    currency: '0x20c0000000000000000000000000000000000000',
    recipient: '0xa726a1CD723409074DF9108A2187cfA19899aCF8',
  })],
})

export const GET =
  mppx.charge({ amount: '0.01', description: 'Random stock photo' })
  (async () => {
    const res = await fetch('https://picsum.photos/1024/1024')
    return Response.json({ url: res.url })
  })
```

```ts [Hono]
import { Hono } from 'hono'
import { Mppx, tempo } from 'mppx/hono'

const app = new Hono()

const mppx = Mppx.create({
  methods: [tempo({
    currency: '0x20c0000000000000000000000000000000000000',
    recipient: '0xa726a1CD723409074DF9108A2187cfA19899aCF8',
  })],
})

app.get(
  '/api/photo',
  mppx.charge({ amount: '0.01', description: 'Random stock photo' }),
  async (c) => {
    const res = await fetch('https://picsum.photos/1024/1024')
    return c.json({ url: res.url })
  },
)
```

```ts [Express]
import express from 'express'
import { Mppx, tempo } from 'mppx/express'

const app = express()

const mppx = Mppx.create({
  methods: [tempo({
    currency: '0x20c0000000000000000000000000000000000000',
    recipient: '0xa726a1CD723409074DF9108A2187cfA19899aCF8',
  })],
})

app.get(
  '/api/photo',
  mppx.charge({ amount: '0.01', description: 'Random stock photo' }),
  async (req, res) => {
    const response = await fetch('https://picsum.photos/1024/1024')
    res.json({ url: response.url })
  },
)
```

```ts [Fetch API]
import { Mppx, tempo } from 'mppx/server'

const mppx = Mppx.create({
  methods: [tempo({
    currency: '0x20c0000000000000000000000000000000000000',
    recipient: '0xa726a1CD723409074DF9108A2187cfA19899aCF8',
  })],
})

Bun.serve({
  async fetch(request) {
    const result = await mppx.charge({
      amount: '0.01',
      description: 'Random stock photo',
    })(request)

    if (result.status === 402) return result.challenge

    const res = await fetch('https://picsum.photos/1024/1024')
    return result.withReceipt(Response.json({ url: res.url }))
  },
})
```

:::

### Test the endpoint

```bash
# Create account funded with testnet tokens
$ npx mppx account create

# Make a paid request
$ npx mppx http://localhost:3000/api/photo
```

::::

## Next steps

<Cards>
  <Card icon="lucide:repeat" title="Accept pay-as-you-go payments" description="Session-based billing with payment channels" to="/docs/guide/machine-payments/pay-as-you-go" />

  <Card icon="lucide:server" title="Server quickstart" description="Framework middleware reference" to="/docs/guide/machine-payments/server" />

  <Card icon="lucide:book-open" title="Full charge reference" description="Complete tempo.charge API documentation" to="https://mpp.dev/payment-methods/tempo/charge" />
</Cards>
