Fiscal402 Express integration is post-settlement. It does not create the 402 response, authorize the payment, or settle funds.
- Request hits a paid resource.
- Your x402 middleware issues HTTP 402 and the client settles.
- The merchant handler runs after settlement succeeds.
- Fiscal402 records the fiscal event from PAYMENT-RESPONSE evidence.
Lifecycle
| Step | Owner |
|---|---|
| HTTP 402 + requirements | Your x402 stack |
| On-chain / facilitator settle | Your x402 stack |
| PAYMENT-RESPONSE header | Your x402 stack |
| POST /settlements | Fiscal402 |
| EU VAT + UBL + receipt | Fiscal402 |
Middleware
@fiscal402/express is source-only. It is not on npm. Copy it from the Fiscal402 repository, or POST /settlements yourself after the handler.
app.ts
import express from "express";
import { fiscal402Middleware } from "@fiscal402/express"; // source only — not on npm
const app = express();
app.use(express.json());
// Your x402 middleware settles first. Fiscal402 runs AFTER res.end.
app.use(
fiscal402Middleware({
apiKey: process.env.FISCAL402_API_KEY!,
endpoint: "https://api.fiscal402.com",
}),
);
app.get("/inference", (req, res) => {
// Paid resource handler. Do not put the Fiscal402 key in the browser.
res.json({ ok: true });
});
PAYMENT-RESPONSE mapping
If you copy the source Node client, you can pass the settled object instead of assembling fields by hand.
recordSettlement.ts
import { Fiscal402 } from "@fiscal402/node"; // source only — not on npm
const fiscal = new Fiscal402({
apiKey: process.env.FISCAL402_API_KEY!,
origin: process.env.FISCAL402_ORIGIN ?? "https://api.fiscal402.com",
});
const result = await fiscal.recordSettlement({
paymentResponse, // settled x402 PAYMENT-RESPONSE object
timestamp: "2026-09-10T12:00:00.000Z",
buyer: { country: "DE", legalName: "Buyer GmbH" },
supply: { kind: "digital", description: "Inference units" },
});
const receipt = await fiscal.getReceipt(result.id);
const jwks = await fiscal.fetchJwks();
const report = await fiscal.verifyReceipt({ receipt, jwks });