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.1.0.tar.gz (14.5 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.1.0-py3-none-any.whl (12.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: fastmpp-0.1.0.tar.gz
  • Upload date:
  • Size: 14.5 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.1.0.tar.gz
Algorithm Hash digest
SHA256 8d8998b8102ac80084f132b5bcc9c0e240ee2a1f9cf2e755f796ea7828c22b17
MD5 ef9cb50f13ae93cf1d6a3f3c6597b644
BLAKE2b-256 3abec3a8aed454e96afe2ba037eaa53c8c05e65798421ce21a4e719f1bf9487c

See more details on using hashes here.

File details

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

File metadata

  • Download URL: fastmpp-0.1.0-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.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 54435fa08e328b4ceaf007f9f53bd38d6041a81bcf5c3af40b6ddfb21e7ac0f2
MD5 47bdf5c613ce1d11e97f27808444f22d
BLAKE2b-256 4c1ea23cb39da4971ef6d5c48a704c8f5f9c34946bcaf34be9d1bd7789ce01b2

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