/docs/merchants/receipts
Settlement receipts
On every successful payment, the middleware exposes the verified envelope in two places:
res.locals.obscuraSettlement— the parsed settlement object, available to your route handler synchronously.X-Payment-Responseheader — a base64-encoded JSON copy of the same object, sent on the wire so clients can verify on-chain.
Read it in your handler
Pull the queue signature into your response body, log to analytics, or write to your own DB.
import type { Response } from "express";
app.get(
"/article/:id",
pay.charge({ amount: "10000", description: "News article" }),
(req, res: Response) => {
const settlement = (res.locals as {
obscuraSettlement?: {
scheme: "umbra-mixer-v1";
queueSignature: string;
callbackSignature?: string;
recipient: string;
amount: string;
asset: string;
};
}).obscuraSettlement;
res.json({
id: req.params.id,
headline: `Article #${req.params.id}`,
body: "Full article text here…",
queueSig: settlement?.queueSignature ?? null,
});
},
);Shape of the settlement object
type ObscuraSettlement = {
scheme: "umbra-mixer-v1";
queueSignature: string; // base58 Solana tx signature (the mixer queue tx)
callbackSignature?: string; // base58 Solana tx signature (Arcium MPC callback);
// omitted when the SDK reported pending finalization
recipient: string; // base58 ETA pubkey (your merchantEtaAddress)
amount: string; // atomic units string (e.g. "10000" = $0.01 USDC)
asset: string; // base58 SPL mint address
};Verification failures never reach your handler — the middleware
intercepts them with a 402 + {error: "invalid_payment", reason} body
and next() is not called. Your route only runs after a confirmed
on-chain queue transaction.
Decode X-Payment-Response
Clients can verify settlement independently:
const header = response.headers.get("X-Payment-Response");
if (header) {
const receipt = JSON.parse(
Buffer.from(header, "base64").toString("utf8"),
);
console.log(
`Paid! https://solscan.io/tx/${receipt.queueSignature}?cluster=devnet`,
);
}Where it shows up on the dashboard
Every settlement lands in your merchant
dashboard within a second via real-time SSE. Each
row shows the route, the amount, the timestamp, and a Solscan deep-link
to the queue transaction. The full feed is available at
/merchants/payments with cursor pagination.
The encrypted-balance credit lands a tick later — once Obscura's claim daemon (every 2 minutes) scans the mixer tree and pulls the receiver-claimable UTXO into your account.