Lumière PayCheck For agent buildersDocsPlansAccountPayments on Base + Solana

Integration guide

How to connect your agents to Lumière PayCheck. All examples use https://lumierepaycheck.org. The complete API reference and runnable examples (TypeScript and Python) are on GitHub.

The flow

  1. Your agent calls a paid API and gets 402 Payment Required with a price, a payout wallet (payTo), and a network.
  2. Before paying, it asks PayCheck: POST /v1/authorize.
  3. On "allow", it pays (optionally attaching our receipt so your wallet can verify it); on "deny", it doesn't; on "review", it waits for a person on your team.

Authorize a payment

curl https://lumierepaycheck.org/v1/authorize \
  -H "Authorization: Bearer $PAYCHECK_AGENT_KEY" -H "content-type: application/json" \
  -d '{"url":"https://api.seller.example/data","amount":"10000","payTo":"0xSELLER_WALLET","network":"eip155:8453"}'

amount is in the token's smallest unit (USDC: 1000000 = $1). The response:

{
  "decision": "dec_3f1c...",
  "outcome": "allow",
  "reasons": ["all rules passed"],
  "receipt": "eyJ2IjoxLCJraWQiOi...signature",
  "verdict": "proceed",
  "observed": { "payTo": "0xSELLER_WALLET", "amount": "10000", "network": "eip155:8453" }
}
OutcomeWhat to do
allowPay exactly this amount to exactly this wallet. The receipt is valid for 5 minutes.
denyDon't pay. reasons lists every rule that failed.
reviewDon't pay yet. Poll GET /v1/decisions/{decision} until it becomes allow or deny (expires after 24 hours).

In TypeScript:

async function mayPay(url: string, amount: string, payTo: string, network: string) {
  const r = await fetch("https://lumierepaycheck.org/v1/authorize", {
    method: "POST",
    headers: { authorization: `Bearer ${process.env.PAYCHECK_AGENT_KEY}`, "content-type": "application/json" },
    body: JSON.stringify({ url, amount, payTo, network }),
  });
  if (!r.ok) return { outcome: "deny", reasons: [`PayCheck returned ${r.status}`] };   // fail closed
  return r.json();
}

Fail closed: if PayCheck can't be reached or returns an error, don't pay. That's the safe default.

Verify receipts in your wallet

Receipts are payload.signature, both base64url; the signature is Ed25519 over the payload text. Our public key is at /.well-known/paycheck-receipt-key.json (a JWK). A wallet that requires a valid receipt matching the exact URL, amount, and payout wallet can't be tricked into paying anything PayCheck didn't approve. Check exp (5 minutes), and refuse receipts with "test": true in production. Ready-to-use verifiers in TypeScript and Python are in the GitHub examples.

Key-less sign-in

Instead of storing an agent key, an agent can send a short-lived token from the platform it runs on. Link the workload once (account page → Key-less sign-in, or POST /v1/agents/{id}/identities), then send the platform token as the bearer token to /v1/authorize. The token's audience must be https://lumierepaycheck.org.

GitHub Actions

The job needs permissions: id-token: write. Link with platform GitHub Actions and subject repo:ORG/REPO:ref:refs/heads/main (or repo:ORG/REPO:environment:production).

- name: Authorize payment (no stored key)
  run: |
    TOKEN=$(curl -sS -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
      "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=https://lumierepaycheck.org" | jq -r .value)
    curl -sS https://lumierepaycheck.org/v1/authorize -H "Authorization: Bearer $TOKEN" \
      -H "content-type: application/json" -d '{"url":"...","amount":"10000","payTo":"0x..."}'

Google Cloud

Cloud Run, GKE, and Compute Engine can fetch an identity token from the metadata server. Link with platform Google Cloud and the service account's unique ID (a long number) as the subject.

TOKEN=$(curl -sS -H "Metadata-Flavor: Google" \
  "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://lumierepaycheck.org")

Microsoft Azure

Managed identities receive tokens for an application registered in your tenant. Register an application, set its Application ID URI, request tokens for that resource, and link with platform Microsoft Azure, your tenant ID, the managed identity's object ID as the subject, and that Application ID URI as the audience (set via the API).

Kubernetes and others

Use platform Other with your cluster's OIDC issuer URL (for example, an EKS cluster's issuer), and the service account as the subject: system:serviceaccount:NAMESPACE:NAME. Mount a projected service account token with audience https://lumierepaycheck.org. The issuer's discovery document and keys must be reachable over HTTPS from the internet.

Tokens must be signed (RS, PS, or ES algorithms), unexpired, and valid for at most 24 hours. We record which workload made each request, never the token.

Paying us over x402

Our paid routes (full endpoint reports, batch lookups, watches, and Builder or Business plans in USDC) answer 402 Payment Required with two options: USDC on Base and USDC on Solana, at the same price. Any x402 client picks the network its wallet supports; on Solana, the facilitator pays the transaction fee, so your wallet only needs USDC.

Check any endpoint for free

No account needed, 60 requests per minute:

curl "https://lumierepaycheck.org/v1/score?url=https://api.seller.example/data"
curl -X POST https://lumierepaycheck.org/v1/check-payment -H "content-type: application/json" \
  -d '{"url":"https://api.seller.example/data","amount":"10000","payTo":"0xSELLER_WALLET"}'

Use it from AI assistants (MCP)

Add the MCP server to Claude Desktop, Cursor, or any MCP client:

{ "mcpServers": { "lumiere-paycheck": { "type": "http", "url": "https://lumierepaycheck.org/mcp" } } }

Tools: check_endpoint, check_payment, top_endpoints, catalog_stats, get_full_report, and report_outcome.

Verifying webhooks

Alerts, review notifications, and decision streaming are signed with your workspace's secret (admins see it on the account page). The header is x-paycheck-signature: sha256=<hex>, an HMAC-SHA256 of the raw request body:

import { createHmac, timingSafeEqual } from "node:crypto";
function verifyPayCheckWebhook(rawBody: string, header: string | undefined, secret: string) {
  const expected = "sha256=" + createHmac("sha256", secret).update(rawBody).digest("hex");
  return !!header && header.length === expected.length && timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}

Payloads include type: budget_alert, spike_alert, or decision.

Report outcomes (optional)

After paying, tell us whether the response was usable. It helps keep x402 safe for everyone and can trigger our own re-test of the seller: POST /v1/report with the receipt and "outcome": "delivered" or "problem". Owners can turn this off on the account page.

Errors

StatusMeaning
401Missing or invalid key or identity token (detail says which check failed)
402The workspace's plan has expired
403Your role doesn't allow this action
429Rate limit reached (per agent, set by your plan)
Questions? Email hello@lumierepaycheck.org or talk to us about Enterprise.