Interactive examples. Every response on this page is simulated — nothing here moves money, creates a real transaction, or shows live data. The code shown is the real, copy-paste integration; run it in your own NMI / Maverick sandbox.
Lifted Payments

NMI + Maverick · Interactive Examples

Card, ACH, and terminal payments — tied to one POS order. In about 40 lines.

They said this integration was hard. It isn't. NMI handles card-not-present and ACH, Maverick reports your card-present terminal sales, and one reconciliation key ties every rail back to the order. Walk the interactive examples below — every response is simulated, the code is the real thing.

3
payment rails
1
POS order
0
reconciliation headaches
~40
lines of code

The architecture

Three rails → one order → one reconciled report.

This is the exact shape your POS needs: take payment at the register three different ways, and have every one of them roll back to the same order and the same deposit report.

NMI

Card — card-not-present

Collect.js hosted fields tokenize the card in the browser, then your server posts transact.php type=sale. No PCI scope.

source='nmi' · entry=card_not_present
ACH

ACH — eCheck

Bank routing + account post server-side to transact.php payment=check. Bank data isn't PCI card data.

source='nmi' · type=ach_debit
MAV

Card-PRESENT — terminal

A physical PAX terminal rings the sale; it settles into Maverick's batches / authorizations reporting feed.

source='maverick' · entry=card_present · TID 840356
3 rails inNMI · NMI · Maverickcard · ACH · terminal
The order#NL-1042Rivera Wholesale LLC · $463.00
OutUnified reporttxns + deposits, reconciled

The reconciliation spine

Maverick batch.purchaseId == NMI transaction id

That match is the spine. In our integration, Maverick stamps the originating gateway transaction id into purchaseId on the settled batch — so a card sale that ran through NMI lines up with its NMI transaction id, and we enrich the existing row instead of counting it twice. A terminal item with purchaseId: null is usually a card-present-only sale you link to the order via a dropdown — but some networks (e.g. Amex) can settle without a purchaseId, so fall back to a last4 + amount + date match against your NMI rows before treating it as net-new.

NMI Collect.js · styling preview

Hosted-field card capture — restyle it live.

This is how NMI Collect.js hosted fields look in your checkout. Flip the theme presets and watch the field styling change — the exact style JSON updates alongside, ready to paste. Submitting here returns a simulated approval; the real Collect.js tokenize-and-charge code is in the snippet below.

Your checkout secured by Collect.js
Tokenize a card and the parsed NMI response shows here.

Theme / style preset

CollectJS.configure({ … }) style object

live JSON
CollectJS.configure(...) · re-called on preset change — iframes stay mounted

Live · NMI eCheck

ACH debit — bank rails, same API.

Routing + account post straight to your server (bank data isn't PCI card data), then to NMI as payment=check. ACH submits pending and clears in a few business days — we show that honestly.

Submit an eCheck and the pending NMI response shows here.

Live · NMI recurring

Schedule a payment for later — pay-later, built in.

NMI inline custom subscriptions handle the "charge this later / charge it every month" path. A future start_date = the first charge fires later. Cancel proves you own the lifecycle.

Create a schedule and the subscription id shows here.

Maverick · card-present

Track the physical terminal sales.

Sample data

Pull settled card-present sales from Maverick's reporting feed and resolve which physical device rang each one. The settled-batch terminal object is often empty in practice, so in our integration we match each batch to its /reporting/authorizations row by last4 + nearest settlement date, then map the TID to the device.

DateCardAmountTerminalBatchpurchaseIdStatus
Loading terminal sales…

A non-null purchaseId means this terminal row is the same sale that already ran through NMI — we enrich, never double-count. purchaseId: null is usually a card-present-only sale → link it to an order in the POS screen below; but because some networks (e.g. Amex) can settle without a purchaseId, fall back to a last4 + amount + date match against your NMI rows first so you don't double-count one that already came through the gateway.

The POS screen

One order. Pay now, schedule, or tag.

The literal No Limits workflow: at the register the operator pays one of three ways — and all three converge on the same thing: order.transaction_id points at a transaction, paid_method names the rail.

ORDER #NL-1042
Rivera Wholesale LLC · ap@riverawholesale.com
Disposable units × 10 @ $24.00$240.00
Accessory kit × 1 @ $99.00$99.00
Freight × 1 @ $124.00$124.00
Tax$0.00
Total$463.00
No payment captured yet.
Pay-now, schedule, and tag-existing all resolve to the same thing — order.transaction_id now points at a transaction row, and paid_method names the rail.

Recent settled Maverick terminal sales not yet linked to an order. The dropdown is fed by GET /pos/candidates.

Pick a path above; the captured transaction id shows here.

Level 2/3 line-item data · both rails

Attach line-item data — built once, sent right.

Commercial-card sales carry enhanced line-item data the bank and card networks require for acceptance — PO number, per-line commodity codes, tax, ship-from / ship-to. You build it once, generically, from the POS line items plus a small per-merchant template, and emit the correct shape for whichever rail runs the card.

Data requirement

Acquirers and the card networks require this itemized data for a sale to be accepted as a commercial-card transaction.

Security

Richer, structured transaction data strengthens fraud and risk screening on every sale.

Audit trail

A complete, itemized record per sale — PO number, line items, tax, ship-from / ship-to — is an auditable transaction record.

Dispute defense

Itemized Level 3 data is the evidence you present to defend a chargeback or dispute (representment).

One builder · both rails · buildLevel3(lineItems, template, amount)

You input the fields generically — the POS already has the line items, the merchant sets a small template once, and one function reconciles and emits the rail-specific payload. It degrades safely: if it cannot reconcile or a required field is missing, it falls back to a normal sale instead of sending data NMI would silently drop or that Maverick would reject.

  1. 1
    Take the POS line items{ description, quantity, unit_price } — already in the cart; nothing re-keyed.
  2. 2
    Add a per-merchant templateStatic stock values set once: commodity code, unit of measure, ship-from ZIP, summary commodity code.
  3. 3
    Compute each item totalitem_total = round(unit_cost × qty − discount, 2) — tax excluded.
  4. 4
    Reconcile to the chargeΣ item_total + tax + shipping + duty == amount.
  5. 5
    Emit the rail shapeNMI flat item_*_N fields, or Maverick's nested order object with level: 3.
  6. 6
    Fall back if it can'tReconcile fails or a required field is missing → send a normal sale. Never silently dropped on NMI, never a 422 on Maverick.

Field reference · Required vs Optional

Every field is flagged Required or Optional, grouped required-first so the must-send set is obvious at a glance. Required-ness is sourced from the integration modules and the API collections — not guessed.

NMI

Boarded forwarding · silently drops if it doesn't reconcile

"Level III Advantage" is a per-merchant boarded service — boarding only lets the gateway forward L2/L3; you still send every field yourself on the sale (and on captures — a partial capture must carry the data or it's lost). If Σ item_total + tax + shipping + duty ≠ amount (tax excluded from item totals), NMI silently discards the L3 data — the sale still succeeds, but the enhanced data is gone with no error. Reconcile before you send.

Source: server/nmi_level3.py docstring + reconcile logic.

Maverick

No boarding flag · strict 422 · category is an enum

L3 is active on all gateway accounts whenever the order is sent — no boarding step (different from NMI). The gateway strictly validates the order and returns 422 if a required field is missing. The tax detail's category must be a valid enumVAT and National are accepted; Sales is rejected as a category (the separate type field may be "Sales"). Ship-from and ship-to ZIP are required — missing required value → fall back to a normal sale, don't eat the 422.

Source: server/maverick_level3.py docstring + Maverick Postman.

Try it · the generic build

Edit the example line items and template, then watch buildLevel3() reconcile and emit both rail shapes. This computes only the baked-in example in your browser — it calls nothing.

Example · simulated

Line items (from the POS)

Per-merchant template (set once)

Reconciled payload

Unified reporting

Every rail, reconciled to the order.

One table across all three rails, plus the deposit/funding view — exactly what the Lifted portal dashboard compiles. This is sample data; anything you submit in the examples above appears on top of it. The key trick: a card sale that runs through the NMI gateway also lands in Maverick's batch, so it would show twice — we dedupe on purchaseId == NMI txn id and enrich the NMI row instead of double-counting.

Money pipeline · sales → deposits

Watch each sale travel authorization → settlement batch → money-in-the-bank, see exactly what is still pending, and catch anything stuck (slow ACH). Example lifecycle — dates and stages are illustrative and simulated; no live API call was made.

Transactions · all rails → order #NL-1042

DateCustomerRailMethodCard / AcctAmountStatusBatchOrder
Loading reporting…

Deposits / funding

DateSourceGrossFeesCB / ReturnsNet deposited

The whole integration

Tokenize → charge → reconcile. ~40 lines.

The hero claim, in one file: capture a card, take an ACH debit, then reconcile all three rails to the order. Every snippet on this page is copy-paste real and Postman-linked.

Drop-in plugin code

Six functions. Copy, paste, ship.

The "impossible" integration is six small functions. Here they are — real, correct, and runnable in your own NMI / Maverick sandbox. Switch languages, copy, open the matching Postman request. Every result below is an example rendered from baked-in data: nothing here calls an API or shows live money.