Verify receipts
Verify a merchant receipt offline against the published Ed25519 key, and publish your own verifying key at /.well-known/jwks.json.
Every accepted order ships with an Ed25519-signed receipt. Anyone — the buyer, an auditor, a dispute process — can verify it offline, with no call back to Veto.
Verify with your handle
const result = checkout.verifyReceipt(receiptJws);
if (result.valid) {
// claims: MerchantReceiptClaims — sessionId, total, decision, mandateRef, …
console.log(result.claims.sessionId, result.claims.total, result.claims.mandateRef);
} else {
console.error(result.reasonCodes); // e.g. ['RECEIPT_INVALID_SIGNATURE']
}The verified claims are the MerchantReceiptClaims: iss: 'veto-checkout', sub,
sessionId, merchantId, agentId, decision, total, mandateType, mandateRef
(the buyer's mandate subject), policyHash, and inputFingerprint. The order_id is on
the settle response, not the receipt.
Verify from the published key, anywhere
import { verifyMerchantReceipt } from '@veto-protocol/checkout';
const jwks = await fetch('https://shop.acme.example/.well-known/jwks.json').then((r) => r.json());
const result = verifyMerchantReceipt(receiptJws, jwks);Publish your verifying key
Serve your receipt public key so buyers can verify independently:
import { createNodeServer } from '@veto-protocol/checkout/http';
// The node adapter already serves /.well-known/jwks.json from the handle.
// To serve it yourself in a custom framework:
app.get('/.well-known/jwks.json', (_req, res) => {
res.json(checkout.receiptJwks()); // { keys: [Ed25519Jwk] }
});Failure reasons
| Reason | Meaning |
|---|---|
RECEIPT_MALFORMED | The JWT could not be parsed. |
RECEIPT_INVALID_SIGNATURE | Signature did not verify against the merchant key. |
RECEIPT_WRONG_TYPE | Header typ was not the receipt type. |
RECEIPT_WRONG_ISSUER | iss was not the expected merchant issuer. |
RECEIPT_KEY_UNRESOLVED | The verifying key could not be resolved. |
Webhooks
Receive and verify HMAC-SHA256 signed event deliveries from the hosted control plane with the SDK's verifyWebhook helper — the Veto-Signature scheme, replay window, retry schedule, idempotency, and secret rotation.
Merchant privacy
What an on-chain settlement reveals, what per-checkout receiving addresses hide, and the honest tradeoffs — plus where pooling fits for full revenue privacy later.