x402-k8s-operator

module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 25, 2026 License: Apache-2.0

README

x402-k8s-operator

Go License Artifact Hub Release Grafana Dashboard

Kubernetes operator that monetizes any API with per-request payments via the x402 protocol.

Single binary, single Deployment. Patches your existing Ingress to enforce payment on specified paths. Works with any Ingress controller (NGINX, Traefik, etc.) using only the standard networking.k8s.io/v1 Ingress API.

                Internet
                   |
                   v
    +----------------------------+
    |  Your existing Ingress     |  <-- operator patches this
    |  (NGINX / Traefik / etc)   |
    +------+-----------+---------+
           |           |
     paid paths    free paths
           |           |
           v           v
    +-----------------+  +-----------------+
    | x402-k8s-       |  | Backend Service |
    | operator :8402  |  | (your API)      |
    | (payment check) |  +-----------------+
    +--------+--------+
             |
    402 if no payment
    forward if paid
             |
             v
    +-----------------+
    | Backend Service |
    | (your API)      |
    +-----------------+

Quick Start

1. Install the operator

kubectl (single manifest):

kubectl apply -f https://raw.githubusercontent.com/razvanmacovei/x402-k8s-operator/main/install.yaml

Helm:

helm install x402-k8s-operator oci://ghcr.io/razvanmacovei/charts/x402-k8s-operator
2. Create an X402Route

Assuming you already have an Ingress called my-api-ingress:

apiVersion: x402.io/v1alpha1
kind: X402Route
metadata:
  name: my-api-payments
spec:
  ingressRef:
    name: my-api-ingress
  payment:
    wallet: "0xYourWalletAddress"
    network: base-sepolia
    defaultPrice: "0.001"
  routes:
    - path: "/api/*"
      # inherits defaultPrice, all requests pay
    - path: "/health"
      free: true
    - path: "/docs/**"
      free: true

That's it. The operator automatically:

  1. Compiles route rules into an in-memory store
  2. Patches your Ingress: paid paths -> operator service, free paths -> original backend
  3. Serves traffic on port 8402: checks payment -> verifies with facilitator -> proxies to backend

CRD Reference

Example: Per-path pricing with conditional mode
apiVersion: x402.io/v1alpha1
kind: X402Route
metadata:
  name: my-api
spec:
  ingressRef:
    name: my-ingress
  payment:
    wallet: "0x..."
    network: base-sepolia
    defaultPrice: "0.001"
  routes:
    - path: "/api/v1/*"
      # inherits defaultPrice, mode defaults to all-pay
    - path: "/api/v2/**"
      price: "0.01"
      mode: conditional
      conditions:
        - header: "X-Bot-Score"
          pattern: "^(bot|automated)$"
          action: pay
        - header: "User-Agent"
          pattern: "(?i)(claude|openai|anthropic)"
          action: pay
    - path: "/health"
      free: true
    - path: "/docs/**"
      free: true
Spec Fields
Field Type Required Description
ingressRef.name string yes Name of the existing Ingress to patch
ingressRef.namespace string no Namespace of the Ingress (defaults to X402Route's ns)
payment.wallet string yes Wallet address to receive payments
payment.network string yes Blockchain network (see Networks table)
payment.defaultPrice string no Default price for paid routes (e.g. "0.001")
payment.facilitatorURL string no Facilitator URL (defaults to https://x402.org/facilitator)
routes[].path string yes Path pattern (* = one segment, ** = any depth)
routes[].price string no Price override for this path
routes[].free bool no Mark path as free
routes[].mode string no all-pay (default) or conditional
routes[].conditions[] array no Conditions for conditional mode
routes[].conditions[].header string yes HTTP header to inspect
routes[].conditions[].pattern string yes Regex pattern to match
routes[].conditions[].action string yes pay or free when matched
Status Fields
Field Type Description
status.ingressPatched bool Whether the Ingress has been patched
status.ready bool Whether the route is fully active
status.activeRoutes int Number of active route rules
status.conditions []Condition Standard Kubernetes conditions

Architecture

Single pod runs both controller and HTTP proxy as goroutines:

Port Purpose
:8080 /metrics (Prometheus)
:8081 /healthz, /readyz (probes)
:8402 Gateway proxy (traffic)

The controller watches X402Route CRDs and writes compiled routes to an in-memory store. The gateway reads from the store instantly — no ConfigMap polling, no separate Deployment.

Traffic Flow
Client -> Ingress Controller -> x402-k8s-operator :8402 -> payment check -> Original Backend
Payment Protocol (x402)

Implements the x402 specification, compatible with the official Coinbase CDP facilitator.

  • Request: Payment-Signature header (Base64-encoded JSON payload; falls back to X-Payment for compat)
  • 402 Response: PAYMENT-REQUIRED header (Base64-encoded JSON) + JSON body (resource object, amount in atomic units, extra asset metadata)
  • 200 Response: PAYMENT-RESPONSE header (Base64-encoded JSON with transaction hash, network, payer)
  • Facilitator flow: Gateway POSTs {paymentPayload, paymentRequirements} to /verify, then /settle on success
Prometheus Metrics
Metric Type Description
x402_requests_total counter Requests by path, namespace, route, payment status
x402_payment_amount_total counter Payment amounts by path, wallet, network
x402_payment_verification_duration_seconds histogram Facilitator verification latency
x402_proxy_request_duration_seconds histogram Backend proxy latency
x402_active_routes gauge Number of active routes
x402_route_store_updates_total counter Route store update count
Grafana Dashboard

Grafana Dashboard

Import the pre-built dashboard from Grafana.com (ID: 24921) or auto-provision it via Helm:

grafanaDashboard:
  enabled: true
  namespace: monitoring  # namespace where Grafana is deployed

The dashboard includes: request rate by status, revenue tracking, payment verification latency (p50/p95/p99), proxy latency, route table, and pod health.


Local Development

Prerequisites: Go 1.25+, Docker, a local Kubernetes cluster (docker-desktop, Kind, or Minikube).

# Build the manager binary
make build

# Build Docker image
make docker-build

# Deploy to local cluster
make deploy-local

# Apply sample X402Route
make sample

# Remove everything
make undeploy

Testing

With mock facilitator (no blockchain needed)
# Terminal 1: Start a simple backend
python3 -m http.server 9090

# Terminal 2: Start the mock facilitator
go run ./cmd/mock-facilitator/

# Terminal 3: Run the test client
go run ./cmd/test-client/ http://localhost:8402/api/hello

The test client sends two requests:

  1. Without payment -> expects 402 Payment Required
  2. With a mock Payment-Signature header -> expects 200 OK

Production

For production, use a mainnet network with a real USDC wallet:

payment:
  wallet: "0xYourProductionWallet"
  network: base
  defaultPrice: "0.01"
Networks
Network Chain ID USDC Contract
base eip155:8453 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
base-sepolia eip155:84532 0x036CbD53842c5426634e7929541eC2318f3dCF7e
avalanche eip155:43114 0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E
avalanche-fuji eip155:43113 0x5425890298aed601595a70AB815c96711a31Bc65
solana solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
solana-devnet solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1 4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU

Prices are human-readable (e.g. "0.001" USDC) and automatically converted to atomic units.


Contributing

Contributions are welcome! See CONTRIBUTING.md for guidelines.

Please read our Code of Conduct before participating.

Security

For reporting security vulnerabilities, see SECURITY.md.

License

Apache License 2.0

Directories

Path Synopsis
api
v1alpha1
Package v1alpha1 contains API Schema definitions for the x402.io v1alpha1 API group.
Package v1alpha1 contains API Schema definitions for the x402.io v1alpha1 API group.
cmd
manager command
test-client command
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL