Skip to main content
Vouch uses a webhook-driven payment reconciliation model. When a buyer transfers funds into a Nomba Virtual Account, Nomba fires a virtual_account.funded event directly to the Vouch backend. Vouch validates the signature, reconciles the payment, and advances the escrow state machine automatically — no polling or manual confirmation needed from your integration.

How It Works

You do not need to register or configure anything for this to work. The webhook endpoint is already configured on the Nomba dashboard for your sub-account.

Signature Verification

Every incoming Nomba request is signed with HMAC-SHA256 over the raw request body, delivered in the nomba-signature header. Vouch verifies this before processing any event — requests with a missing or mismatched signature are rejected with 401.
The signature is computed over the raw request bytes. The Vouch backend applies express.raw() middleware to this route to prevent JSON parsing from modifying the body before the signature check.

Supported Event Types


Partial Payments

If a buyer sends multiple transfers that collectively equal the agreed amount, Vouch handles it automatically. Each virtual_account.funded event increments the running amountReceived total: Your integration only needs to watch for FUNDED before allowing work to begin. You do not need to track individual transfers.

Overpayment Handling

When the accumulated amountReceived exceeds totalAmount by more than 1%, Vouch:
  1. Sets the agreement to OVERFUNDED
  2. Calculates excess = amountReceived - totalAmount
  3. Reads the sender’s bank details from the webhook payload
  4. Immediately calls the Nomba transfer API to refund the excess to the original sender
  5. Logs the outcome in your developer audit log as OVERPAYMENT_FLAGGED
Automatic refunds require the sender’s account number and bank code to be present in the Nomba webhook payload. If these details are missing, the refund is skipped and logged with a reason — you can handle it manually from the developer dashboard.

Idempotency

Every Nomba event carries a unique requestId. Vouch stores this as nombaReference on the transfer record, which has a database-level unique constraint. If Nomba retries a delivery (common in production), the duplicate is detected and silently dropped — the agreement is never double-credited.

Developer Audit Log Events

Every reconciliation writes a structured entry to your developer log, visible in the dashboard:

Polling as a Fallback

If you need to check agreement status from your frontend or in a background job, use vouch.escrow.status() at any time:
For waiting on payment confirmation, a lightweight polling loop with a 5-second interval is a reliable approach for most bank transfer windows:
For instant bank transfers (NIP), a 5-second poll interval over 24 attempts covers a 2-minute window — enough for the vast majority of payments. For manual transfers, consider a longer window or a user-triggered re-check button.