Research prototype. Synthetic data and simulated payments only — not an official or production security service. Limitations

Tumaini Core · integration example

Verify a payment request before the money moves.

A working integration for the fictional Falcon Demo Bank. Its bill-payment screen asks Tumaini to verify the signed request against the exact amount and account about to be paid. Every call below goes to the live Tumaini backend — nothing is mocked.

  1. 01

    The bank signs

    POST /api/v1/sandbox/receipt issues an Ed25519-signed receipt for AED 150.00 to one account, for one customer.

  2. 02

    The app verifies

    POST /api/v1/verify/receipt with the message text and the payment the customer is about to make.

  3. 03

    Pay or refuse

    Proceed only when valid is true. Any change to text, amount, account or recipient fails a named check.

FFalcon Demo Bank · Pay a bill

Fictional bank

Start by having the bank issue a request. This calls the live sandbox endpoint and returns a real Ed25519-signed receipt.

Live API traffic

Real requests · newest first

Requests to the Tumaini API appear here exactly as sent and received (long receipts are shortened for display).

The same integration in a few lines of Node.js

Also in the repository at examples/falcon-bank/verify-before-pay.mjs. No API key is needed for verification in the prototype; calls are rate-limited per IP.

// examples/falcon-bank/verify-before-pay.mjs — run: node verify-before-pay.mjs
const BASE = process.env.TUMAINI_BASE_URL ?? "https://tumaini-tau.vercel.app";

// 1. In production the bank signs in its own systems. Here, the sandbox signs for the fictional bank.
const issued = await fetch(`${BASE}/api/v1/sandbox/receipt`, { method: "POST" }).then((r) => r.json());

// 2. Before paying, the bank's app verifies the receipt against the exact payment it is about to make.
const res = await fetch(`${BASE}/api/v1/verify/receipt`, {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    receipt: issued.receipt,
    content: issued.content,
    audience: issued.audience,
    intended_action: { type: "payment", payment: issued.payment },
  }),
}).then((r) => r.json());

if (!res.valid) throw new Error(`Blocked: ${res.outcome}`);
console.log("Verified by", res.issuer.display_name, "— proceed with this payment only.");

Full API reference →