Skip to content

x402 Support

Dhali supports the x402 standard for HTTP-based payments. This allows for a standardized way to handle payments and resource discovery in a machine-to-machine economy.

Overview

The x402 protocol provides a way for resource servers to:

  1. Advertise payment requirements via standard HTTP headers.
  2. Verify payments through a facilitator.
  3. Standardize pricing across different networks and assets.

Resource Server Example (Python)

Below is a complete example of an x402 resource server built with FastAPI. This server uses the x402 middleware to handle payment verification automatically.

Setup

You will need the x402 and fastapi Python packages:

pip install x402 fastapi

Implementation

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import json

import x402.http as x402_http
from x402 import AssetAmount, Network, PaymentRequirements, Price, SupportedKind, x402ResourceServer
from x402.http.middleware import fastapi_payment_middleware
from x402.schemas import FacilitatorConfig

class DhaliSchemeNetworkServer:
    @property
    def scheme(self) -> str:
        return "dhali"

    def parse_price(self, price: Price, network: Network) -> AssetAmount:
        return price

    def enhance_payment_requirements(self, requirements: PaymentRequirements, supported_kind: SupportedKind, extensions: list[str]) -> PaymentRequirements:
        return requirements

class DhaliPaywallProvider:
    def generate_html(self, payment_required, config=None):
        return json.dumps(accepts)

facilitator_url = "https://x402.api.dhali.io/v2/..."
accepts = {"scheme":"dhali","network": ...}

dhali_schema = DhaliSchemeNetworkServer()

app = FastAPI(title="Dhali Paid Resource")

facilitator = x402_http.HTTPFacilitatorClient(FacilitatorConfig(url=facilitator_url))

x402_server = x402ResourceServer(facilitator)
x402_server.register(accepts["network"], dhali_schema)

routes = {
    "GET /*": {
        "accepts": [accepts],
    },
}

@app.middleware("http")
async def x402_middleware(request, call_next):
    return await fastapi_payment_middleware(routes=routes, server=x402_server, paywall_config=None, paywall_provider=DhaliPaywallProvider())(request, call_next)

@app.get("/data")
async def get_paid_data(request: Request):
    return JSONResponse({"message": "Here is your paid data"})

How to use

1. Get your facilitator and accepts payload

Navigate to Dhali Portal, link your wallet, and create a new asset. Then, go to your new asset's dashboard page and copy your x402 address and accepts payload into the variables facilitator_url and accepts above.

2. Spin up the above server

After following the above prerequisite, save the implementation example above as main.py and run it using uvicorn:

uvicorn main:app --reload --port 8001

Your server will be running at http://127.0.0.1:8001.

3. Create an x402 payment signature

To access the /data endpoint, you need a valid payment signature.

  1. Get the payment-required header from your server. You will need this to build the x402 payment-signature header in the next steps:

    curl -v http://127.0.0.1:8001/data
    

    You should see the payment-required header in the output.

  2. Navigate to the Dhali Payment Terminal, or use our Python or JavaScript libraries. Deposit sufficient funds into your payment channel and create a payment signature (ensure you use the correct currency and network as defined in your API's dashboard).

  3. Once the payment is created, copy the x402 payment signature (this is a base64 encoded payload).

4. Send a request with the signature

Use curl to send a request to your local server, including the signature in the payment-signature header:

curl -v -H "payment-signature: <your_copied_signature>" http://127.0.0.1:8001/data

If the signature is valid, your server will respond with:

{"message": "Here is your paid data"}

Tip (Debugging failed requests):

If the request fails (e.g. you receive another 402), inspect the returned payment-required header. This header is base64-encoded — decode it to see the facilitator’s structured error:

echo "<payment-required-header>" | base64 -d | jq

This often reveals issues such as wrong network, asset mismatch, insufficient channel balance, or an expired claim.