Skip to main content

MPP-based payment gating for FastAPI

Project description

fastapi_mpp

MPP-based payment gating for FastAPI. Add a single decorator to any route and it handles the full 402 → pay → verify flow automatically.

Quick start

from fastapi import FastAPI
from fastapi_mpp import ChargeableFactory, PaymentMethod

app = FastAPI()

factory = ChargeableFactory.create(
    PaymentMethod.tempo(
        currency="0x20C000...",   # USDC token address
        recipient="0xYourWallet",
    ),
    realm="my-api",               # shown in WWW-Authenticate
    secret_key="...",             # or set MPP_SECRET_KEY env var
)

@app.get("/premium")
@factory.Chargeable(amount="0.50", description="Premium data")
async def premium():
    return {"data": "paid content"}

Without a valid payment credential the route returns:

HTTP/1.1 402 Payment Required
WWW-Authenticate: MPP realm="my-api", ...

{"error": "Payment Required", "challenge": {...}}

With a valid credential the route runs and responds:

HTTP/1.1 200 OK
Payment-Receipt: MPP receipt=...

{"data": "paid content"}

Factory config reference

ChargeableFactory.create(*methods, realm=None, secret_key=None)

Parameter Type Description
*methods positional Exactly one PaymentMethod.*() result. Multi-method support is planned.
realm str | None Server realm for WWW-Authenticate. Falls back to MPP_REALM env var.
secret_key str | None HMAC secret for challenge signing. Falls back to MPP_SECRET_KEY env var.

PaymentMethod.tempo() config reference

Parameter Type Default Description
currency str | None None Default currency token address (e.g. USDC).
recipient str | None None Default recipient wallet address.
decimals int 6 Token decimal places.
rpc_url str | None None Override the Tempo RPC endpoint.
chain_id int | None None 4217 = mainnet, 42431 = testnet (Moderato).
fee_payer_key str | None None Hex private key (0x-prefixed) for gas-sponsored transactions.
root_account str | None None Root account address for access key signing.
client_id str | None None Optional client identity for attribution memos.
enable_store bool False Enable in-memory replay protection (prevents credential reuse).

Decorator config reference

@factory.Chargeable(amount, *, ...)

Parameter Type Default Description
amount str required Human-readable charge amount, e.g. "0.50".
currency str | None None Override the method-level default currency for this route.
recipient str | None None Override the method-level default recipient for this route.
description str | None None Human-readable payment description shown to the payer.
expires str | None None ISO 8601 challenge expiry. Defaults to now + 5 minutes.
attach_receipt bool True Set Payment-Receipt header on successful payment.
on_payment async (credential, receipt) -> None None Async callback fired after each successful payment.

Optional middleware

MppMiddleware attaches the Mpp instance to request.state.mpp for advanced use cases:

from fastapi_mpp import MppMiddleware

app.add_middleware(MppMiddleware, factory=factory)

@app.get("/advanced")
async def route(request: Request):
    mpp = request.state.mpp
    result = await mpp.charge(
        authorization=request.headers.get("Authorization"),
        amount="1.00",
    )
    ...

Testing with npx mppx

mppx is the MPP CLI test client. Run your FastAPI app locally, then:

# Install once
npm install -g mppx

# Hit a gated endpoint — mppx handles the 402 → wallet → credential flow
npx mppx http://localhost:8000/premium

# Specify a wallet private key
npx mppx --key 0xYourPrivateKey http://localhost:8000/premium

# Testnet (Moderato)
npx mppx --network moderato http://localhost:8000/premium

Start the example app:

export MPP_SECRET_KEY=dev-secret
export MPP_REALM=example-api
export TEMPO_CURRENCY=0x20c0000000000000000000000000000000000000   # Tempo PATH/USD (testnet)
export TEMPO_RECIPIENT=0xYourWalletAddress

uv run fastapi dev examples/basic.py

Running tests

uv sync --group dev
uv run pytest

Run a single test file:

uv run pytest tests/test_402_flow.py -v

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastmpp-0.2.1.tar.gz (14.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastmpp-0.2.1-py3-none-any.whl (12.7 kB view details)

Uploaded Python 3

File details

Details for the file fastmpp-0.2.1.tar.gz.

File metadata

  • Download URL: fastmpp-0.2.1.tar.gz
  • Upload date:
  • Size: 14.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.1 {"installer":{"name":"uv","version":"0.11.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for fastmpp-0.2.1.tar.gz
Algorithm Hash digest
SHA256 2ff8c44ec98301627b6095c65424a4f7b40294d387874a8bc7e758675a7699fc
MD5 160e785bf8f810f2fd01da43674588c3
BLAKE2b-256 daf12bcd4fef52229e3188a70f56892da72d868f305c40be86832947198ed2d9

See more details on using hashes here.

File details

Details for the file fastmpp-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: fastmpp-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 12.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.1 {"installer":{"name":"uv","version":"0.11.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for fastmpp-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2fca518f95c64a72bc3e7b76471940880ad895000e6c2a0bfbe9a16b8b2c60d3
MD5 a26074a2480f03d458dc74e9f3b8cc70
BLAKE2b-256 51136e71ee15e50439cabb09d829afc5058d6b52652a531adec4445a49b80d0c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page