Add signed receipts to your Express.js API in under 5 minutes. Every response will include a PEAC-Receipt header with a verifiable JWS.
- Node.js >= 22.0.0
- An existing Express.js application (or create one below)
pnpm add @peac/middleware-express @peac/protocol @peac/crypto expressimport { generateKeypair, exportJWK } from '@peac/crypto';
const { publicKey, privateKey } = await generateKeypair();
const jwk = await exportJWK(publicKey, privateKey);
console.log(JSON.stringify(jwk, null, 2));
// Save this JWK securely. Share only the public key.import express from 'express';
import { peacMiddleware } from '@peac/middleware-express';
const app = express();
app.use(
peacMiddleware({
issuer: 'https://api.example.com',
signingKey: {
kty: 'OKP',
crv: 'Ed25519',
x: '<base64url public key from step 2>',
d: '<base64url private key from step 2>',
},
keyId: 'prod-2026-03',
})
);
app.get('/api/data', (req, res) => {
res.json({ message: 'Hello World' });
// PEAC-Receipt header is automatically added to the response
});
app.listen(3000, () => console.log('Server running on port 3000'));curl -i http://localhost:3000/api/dataYou should see a PEAC-Receipt header in the response containing a compact JWS.
In a separate script or on the consumer side, verify the receipt using the issuer's public key:
import { verifyLocal } from '@peac/protocol';
import { importPublicKey } from '@peac/crypto';
// The issuer's public key (from the JWK saved in step 2, public part only)
const publicKey = await importPublicKey({
kty: 'OKP',
crv: 'Ed25519',
x: '<base64url public key from step 2>',
});
const receiptJws = '<the PEAC-Receipt header value from the curl response>';
const result = await verifyLocal(receiptJws, publicKey);
console.log('Valid:', result.valid);
if (result.valid) {
console.log('Issuer:', result.claims.iss);
console.log('Kind:', result.claims.kind);
}- Every API response carries a signed receipt
- Receipts verify offline with just the public key
- No network calls needed for verification
- Receipts survive across organizational boundaries
- Publish your policy: see PEAC-TXT for
/.well-known/peac.txt - Publish your keys: see PEAC-ISSUER for
/.well-known/peac-issuer.json - Add typed extensions: see Wire 0.2 spec for commerce, access, identity groups
- See examples/pay-per-inference for a full 402 payment flow