Skip to content

Verify a Hedera transaction by memo

A common need: "did this buyer pay me, and which order was it for?" On Hedera, the transaction memo is how you tie an on-chain payment back to an order or invoice. This guide shows how to verify a Hedera transaction by memo with hbar-kit — server-side, read-only, through the Mirror Node.

Use the memo as your order id

Give every order a unique memo (e.g. order_<uuid>) and ask the buyer to set it on their transfer. Then verification can match exactly one payment to exactly one order:

ts
import { verifyHbarPayment } from "@hbar-kit/payments"

const result = await verifyHbarPayment({
  network: "mainnet",
  receiver: "0.0.12345",
  amount: "25",
  memo: "order_6471727153206", // your order / invoice id
  after: new Date(Date.now() - 60 * 60 * 1000),
})

if (result.matched) {
  console.log("Paid order_6471727153206 in", result.transactionId)
}

What the memo match does

  • Transactions that credit receiver but carry a different memo are excluded.
  • If transactions reached the receiver but none match the memo, status is "mismatch".
  • If no transaction reached the receiver at all in the window, status is "pending".
  • When exactly one transaction matches the memo and the amount, status is "confirmed" and result.matched is true.

Loosen the comparison when you need to

Memos can arrive with stray whitespace or inconsistent casing from different wallets. Control how strictly the memo is compared with memoComparison:

ts
const result = await verifyHbarPayment({
  network: "mainnet",
  receiver: "0.0.12345",
  amount: "25",
  memo: "ORDER_6471727153206",
  memoComparison: { mode: "caseInsensitive" }, // "exact" (default) | "trim" | "caseInsensitive"
  after: new Date(Date.now() - 60 * 60 * 1000),
})
  • "exact" — byte-for-byte (default).
  • "trim" — ignore leading/trailing whitespace.
  • "caseInsensitive" — ignore case (and whitespace).

Memo + amount + window together

The memo is one of three filters. For robust verification combine all three:

  • memo — which order this payment is for.
  • amount (+ optional comparison: "atLeast") — that the right amount arrived.
  • after / before — that it happened in the expected window. (Mirror Node caps a single timestamp range at ~7 days.)

If you only need "did any qualifying payment arrive for this order", keep comparison: "exact" and inspect status. If overpayment should still count, use comparison: "atLeast".

Why server-side

A buyer can claim any memo or amount. The Mirror Node is the source of truth: hbar-kit reads the actual on-chain transfer and its real memo. Always run this on the server and derive receiver, amount, and memo from your own records — never from client input.

See also: Build a Hedera payment link and Accept HBAR payments without custody.