Skip to content

longern/Meteria402

Repository files navigation

Meteria402

Meteria402 is a Cloudflare Workers gateway that turns AI API usage into x402 payments. It exposes OpenAI-compatible and provider-native routes through Cloudflare AI Gateway, tracks usage in D1, gates requests with deposit-backed accounts and invoices, and supports wallet-based login plus scoped autopay settlement.

The intended flow is:

Client / provider SDK
  -> /v1/*, /compat/*, or provider-native routes
  -> Meteria402 account and invoice checks
  -> Cloudflare AI Gateway provider endpoint
  -> usage-based invoice creation
  -> x402 invoice payment before the next request

Current scope

This implementation includes:

  • Anonymous deposit quote and settlement endpoints.
  • API key generation after a settled deposit.
  • D1-backed accounts, API keys, requests, invoices, payments, and append-only ledger entries.
  • Provider SDK endpoint proxying through Cloudflare AI Gateway.
  • Usage-based invoice creation after successful requests.
  • Blocking of new model requests when an unpaid invoice exists.
  • Optional autopay-worker integration for deposit and invoice settlement.
  • A minimal same-origin /console page for deposit setup and account inspection.

D1 is the billing source of truth. Durable Objects are used only for short-lived login coordination and account request gates.

Pages

  • / — Home page with gateway overview.
  • /console — Account dashboard for deposits, API keys, usage, invoices, and autopay.
  • /login — Owner-wallet login on the main site, with injected-wallet signing or scan login.
  • /pay-deposit — Standalone deposit payment page for wallets that do not expose window.ethereum (mobile / non-ETH browsers). Deep-link or QR-code based.

x402 defaults

When unset, the Worker defaults to Coinbase CDP's hosted x402 facilitator and Base mainnet:

X402_FACILITATOR_URL = "https://api.cdp.coinbase.com/platform/v2/x402"
X402_NETWORK = "eip155:8453"
X402_ASSET = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"

That network is Base mainnet, and the asset is native USDC on Base.

Set your recipient wallet before using real payments:

wrangler secret put X402_RECIPIENT_ADDRESS

If your facilitator requires authentication, set one of:

# For CDP JWT authentication (preferred)
wrangler secret put CDP_API_KEY_ID
wrangler secret put CDP_API_KEY_SECRET

# Or for legacy token auth
wrangler secret put X402_FACILITATOR_AUTH_TOKEN

Setup

Install dependencies:

npm install

Create a D1 database:

wrangler d1 create meteria402

Copy the returned database ID into wrangler.toml, then apply migrations:

npm run db:migrate:local

For a deployed D1 database, apply the same migrations remotely:

npm run db:migrate:remote

Set required secrets for deployed usage:

wrangler secret put CLOUDFLARE_ACCOUNT_ID
wrangler secret put CLOUDFLARE_API_TOKEN
wrangler secret put AI_GATEWAY_API_KEY
wrangler secret put X402_RECIPIENT_ADDRESS
wrangler secret put X402_RECIPIENT_PRIVATE_KEY

CLOUDFLARE_API_TOKEN is used only for AI Gateway log reconciliation and needs Cloudflare AI Gateway read access for the configured account/gateway.

Billing costs are multiplied by BILLING_COST_MULTIPLIER before invoices are created. This is intended to cover card processing fees and similar transaction costs. If unset, the Worker defaults to 1.055.

For a gateway that requires Cloudflare AI Gateway authentication, also set:

wrangler secret put AI_GATEWAY_AUTH_TOKEN

To prefill /console with a default payment worker URL at frontend build time, set:

export VITE_DEFAULT_AUTOPAY_URL="https://autopay.example.com"

For autopay pre-authorizations, the main Worker signs each /api/pay request with an EIP-712 requester wallet proof. X402_RECIPIENT_PRIVATE_KEY must match X402_RECIPIENT_ADDRESS; it identifies the main site's recipient/refund wallet and is not the user's owner wallet or the autopay payer hot wallet. Set AUTOPAY_REQUESTER_ORIGIN when background jobs need to use stored autopay capabilities outside an incoming request, and optionally set AUTOPAY_REQUESTER_NAME for the label shown on the autopay authorization page. The same recipient private key is also used to derive the HMAC key for login, session, quote, and autopay state tokens.

Run locally:

npm run dev

npm run dev and npm run deploy build the React console into dist/client before starting or deploying the Worker. API routes still run through the Worker, while /console is served as a single-page app.

Open:

http://localhost:8787/console

Development payments

Local development can bypass facilitator settlement by setting:

ALLOW_DEV_PAYMENTS = "true"
DEV_PAYMENT_PROOF = "<local random proof>"

Then /console can settle a quote using:

{ "dev_proof": "<local random proof>" }

Do not enable development payments in production. The proof must be a local secret; there is no built-in fixed proof string.

API

This is the main route surface exposed by the Worker.

Authentication

  • GET /api/session — Returns the current session identity (owner address and expiry) or null.
  • POST /api/login/challenge — Creates a short-lived main-site wallet login challenge.
  • POST /api/login/complete — Verifies the wallet signature and sets the session cookie.
  • POST /api/login/scan/start — Creates a QR/deeplink login request backed by a Durable Object.
  • GET /api/login/scan/:id/details — Get public scan-login request details.
  • GET /api/login/scan/:id/events — Hibernatable WebSocket stream for scan-login status.
  • POST /api/login/scan/:id/challenge — Creates the wallet-page challenge for a scan login.
  • POST /api/login/scan/:id/approve — Verifies the wallet-page signature and approves the scan login.
  • POST /api/login/scan/:id/deny — Rejects a pending scan login request.
  • POST /api/login/scan/:id/complete — Completes the desktop browser login after approval.
  • POST /api/logout — Clears the session cookie.
  • POST /api/session/autopay — Updates the account autopay endpoint stored in D1.

Deposits

  • POST /api/deposits/quote — Create a refundable deposit quote.
  • GET /api/deposits/intent — Load a signed deposit intent for standalone payment pages.
  • POST /api/deposits/settle — Settle a deposit via x402 (browser wallet, mobile deep-link, or dev bypass).
  • POST /api/deposits/:id/autopay/start — Start autopay settlement for a deposit quote.
  • POST /api/deposits/:id/autopay/complete — Complete autopay settlement for a deposit quote.
  • GET /api/deposits — List your deposit history.

Account

  • GET /api/account — Get deposit balance, unpaid invoice total, and status.
  • PATCH /api/account — Update account settings, including minimum autopay recharge amount.
  • POST /api/account/owner-rebind/challenge — Create an owner-wallet rebind challenge.
  • POST /api/account/owner-rebind/complete — Complete an owner-wallet rebind.
  • GET /api/api-keys — List API keys.
  • POST /api/api-keys — Create a new API key.
  • POST /api/api-keys/:id/disable — Disable an API key.
  • POST /api/api-keys/:id/enable — Re-enable a disabled API key.
  • DELETE /api/api-keys/:id — Soft-delete an API key.
  • GET /api/invoices — List invoices.
  • GET /api/requests — List model calls / usage records.
  • POST /api/reconcile — Manually trigger pending AI Gateway usage reconciliation.
  • POST /api/refund — Request a refund settlement.

Invoice Payment

  • POST /api/invoices/:id/pay/quote — Create a payment quote for an unpaid invoice.
  • POST /api/invoices/:id/pay/settle — Settle an invoice payment.
  • POST /api/invoices/:id/pay/autopay/start — Start autopay invoice settlement.
  • POST /api/invoices/:id/pay/autopay/complete — Complete autopay invoice settlement.

Autopay

  • GET /api/autopay/capabilities — List scoped autopay authorizations (limits, remaining budget, expiry).
  • POST /api/autopay/capabilities — Create a new scoped autopay limit.
  • DELETE /api/autopay/capabilities/:id — Revoke an autopay authorization.
  • POST /api/autopay/capabilities/:id/complete — Complete the approval after wallet signature.
  • GET /api/autopay-wallet/balance — Query the autopay wallet address and USDC balance.

Gateway

  • POST /v1/* — OpenAI native endpoints. Proxied to Cloudflare AI Gateway /openai/*.
  • POST /compat/* — Cloudflare unified OpenAI-compatible endpoints. Proxied to AI Gateway /compat/*.
  • POST /anthropic/*, /google-ai-studio/*, /openrouter/*, /mistral/*, /groq/*, /deepseek/*, /perplexity/*, /grok/*, /workers-ai/*, /azure-openai/*, /cohere/*, /replicate/*, and /huggingface/* — provider-native Gateway endpoints.
  • GET requests under these provider paths are proxied without creating usage invoices.
  • GET /health — Service health check.
  • GET /api/config — Public frontend configuration (min deposit, asset decimals, etc.).

Use the generated API key with any OpenAI-compatible client:

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "mia2_xxx",
  baseURL: "https://your-worker.example.com/v1",
});

const response = await client.chat.completions.create({
  model: "gpt-5-mini",
  messages: [{ role: "user", content: "Hello" }],
});

For the Cloudflare unified OpenAI-compatible endpoint, use:

const client = new OpenAI({
  apiKey: "mia2_xxx",
  baseURL: "https://your-worker.example.com/compat",
});

await client.chat.completions.create({
  model: "openai/gpt-5-mini",
  messages: [{ role: "user", content: "Hello" }],
});

If the previous request created an unpaid invoice, the next model request returns:

{
  "error": {
    "type": "payment_required",
    "code": "unpaid_invoice",
    "message": "An unpaid invoice must be paid before making another request."
  }
}

Notes

  • API keys are shown only once.
  • Account ownership is controlled by the owner wallet stored as owner_address, not by API keys. If an API key is lost, sign in with the owner wallet and create a new key from /console.
  • Owner-wallet loss recovery is not implemented. Rebinding currently requires the existing owner wallet to sign the change.
  • Streaming responses are proxied through without buffering; billing relies on Cloudflare AI Gateway log reconciliation.
  • Successful metered requests are marked pending_reconcile first. Billing is delayed until the Worker can read the Cloudflare AI Gateway log cost, then the request is settled and an invoice is created.
  • AI Gateway log reconciliation runs shortly after the response with waitUntil retries and is swept again by the scheduled Worker trigger.

About

x402 billing gateway for AI APIs on Cloudflare Workers, with D1 usage accounting, OpenAI-compatible routes, wallet login, and scoped autopay.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors