Veto/docs
Meow Gateway

Accounts Payable pipeline

Invoice → capsule → payment, with HITL for first-time payees and wires over $5k.

End-to-end: an agent receives an invoice, extracts the payee, gets a human approval where policy demands one, and pays via Meow.

Pack

Use bundled ap_strict_v1. Key rules:

  • require_invoice_for_pay — every meow.pay must bind invoice_hash
  • require_verified_beneficiary — first-time payees need HITL
  • require_approval_wire_over_5k — every wire ≥ $5k needs HITL

Flow

import { VetoMeow } from "@veto/meow";

const veto = new VetoMeow({ baseUrl: "http://localhost:3005" });

// 1. Upload invoice bytes; the parser extracts vendor + total.
const invoice = await veto.invoices.ingest({
  content_type: "application/pdf",
  bytes_base64: pdfBytes.toString("base64"),
  uploaded_by: "agent_finance_bot"
});

// 2. Upsert the counterparty. First-time payees start quarantined.
const payee = await veto.counterparties.upsert({
  type: "bank_us",
  display_name: invoice.parsed.vendor_name,
  routing_number: "021000021",
  account_last4: "1234",
  account_holder_name: invoice.parsed.vendor_name,
  operator_id: "agent_finance_bot"
});

// 3. Mint the capsule. If the beneficiary is still unverified,
//    the gateway responds 409 with an approval_id.
let mint;
try {
  mint = await veto.capsules.mint({
    entity_id: "ent_acme_llc",
    agent_id: "agent_finance_bot",
    tool: "meow.pay",
    rail_allowlist: ["ach"],
    counterparty_hash: payee.beneficiary_hash,
    amount_ceiling: { currency: "USD", amount: invoice.parsed.total_usd },
    invoice_hash: invoice.content_hash,
    workflow_id: newWorkflowId(),
    ttl_seconds: 900
  });
} catch (e) {
  if (e.code === "approval_required") {
    // Human clicks approve in the dashboard.
    // On approval, retry the mint with approval_ref: e.approval_id.
    throw e;
  }
  throw e;
}

// 4. Consume → forwards to Meow.
const result = await veto.consume({
  jws: mint.jws,
  tool: "meow.pay",
  rail: "ach",
  counterparty_hash: payee.beneficiary_hash,
  amount: { currency: "USD", amount: invoice.parsed.total_usd },
  memo: `invoice ${invoice.parsed.invoice_number}`
});

console.log("paid:", result.upstream.meow_payment_id);

What the receipt chain captures

After one run, the entity's receipt chain shows:

  1. Genesis receipt from onboarding submit
  2. Allow receipt from the invoice ingest (if you wired that into mint)
  3. Allow or require_approval receipt from the mint
  4. (If approval required) Allow receipt from the approval resolve
  5. Allow receipt from consume, with rail: ach, amount: $X, pointing at the capsule
  6. Allow receipt from the Meow settlement webhook

Every step is cryptographically linked. A month from now, you can verify the chain without talking to the agent, the gateway, or Veto.