Dexter
Dexter
Docs
Tabs

Verified against @dexterai/x402 5.3.1 · 2026-07-07

What is a tab

By the end of this page you will be able to explain what a tab is, tell it apart from an MPP session, and decide when to reach for one instead of paying per call.

A tab is a capped payment channel between one buyer and one seller. You open it once with a spending cap. After that your agent keeps calling the seller and pays out of the tab on each call, with no new transaction and no new approval per call. When you are done you close the tab, and a single on-chain settlement pays the seller for exactly what was metered.

The tab primitive ships in @dexterai/x402/tab. The channel is rooted in a non-custodial Solana vault: your USDC stays in your own wallet the whole time, and the cap is enforced by the on-chain program, not by this SDK.

The mechanics, in plain words

  1. Open. You call openTab with a vault adapter, the seller's URL, and two caps: perUnitCap (the most a single charge can be) and totalCap (the most the whole tab can ever spend). Opening authorizes a short-lived session key scoped to that one seller and that cap. This is the one consent step. Nothing has been paid yet.

  2. Pay per call. Each call signs a fresh voucher with the session key. The voucher carries a cumulative amount, a running odometer of everything spent on this channel so far. The seller checks that each voucher strictly exceeds the last one and stays under the cap, then serves the response. For streamed responses the seller demands a new voucher before each chunk, so you are paid up exactly to what you have received.

  3. Crystallize. As you spend, the accrued charges crystallize on chain into a reservation sized to exactly what has been spent, never the whole wallet. The rest of your balance stays fully yours to spend or withdraw. This is a keyless cadence the facilitator drives; the seller does not tune it and neither do you.

  4. Close. You call tab.close(). The final voucher is posted to the facilitator's settle endpoint, which lands one on-chain transaction paying the seller's address for everything metered. TabCloseResult.settleTx is the real settlement signature.

The buyer-side shape of that loop, typed against 5.3.1:

tab-shape.ts
import { openTab } from '@dexterai/x402/tab';
import type { Tab } from '@dexterai/x402/tab';
 
// `vault` is built once from your wallet — see "Tabs from a browser"
// or "Tabs from a Node agent" for how it is produced.
const tab: Tab = await openTab({
  vault,
  network: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
  seller: 'https://api.example.com',
  perUnitCap: '0.01',   // most a single charge can be
  totalCap: '1.00',     // most the whole tab can ever spend
});
 
// Pay per streamed request; the SDK signs a fresh voucher per chunk.
for await (const chunk of await tab.stream('https://api.example.com/paid/tick')) {
  consume(chunk);
}
 
const { settleTx } = await tab.close(); // one on-chain settle pays the seller

This page shows the shape, not a runnable program — building the vault adapter is the real first step, and it differs for a browser wallet versus a headless agent. The two how-to pages below carry the complete, working setup.

The seller cannot be stranded

The property that makes a tab safe to leave open is that a buyer walking away cannot strand the seller, and a silent seller cannot freeze the buyer.

  • Everything metered crystallizes on chain as you go, into a reservation against your wallet. If your agent crashes or you close the tab, the seller is still owed — and can still be paid — exactly what was already metered.
  • The reservation is sized to what has been spent, not to your whole balance. The rest of your wallet is never locked.
  • If a seller goes silent and never settles, the buyer reclaims the abandoned reservation after a fixed grace period. No one's funds can be frozen indefinitely.

None of that is enforced by this SDK. It is enforced by the Solana vault program at consensus, and only your passkey can move money out of the wallet.

Tab versus paying per call

Paying per call (the payAndFetch / useX402Payment path in the Pay section) settles every request as its own on-chain payment. It is the right tool for occasional or one-off calls, and it works across every chain the package supports.

A tab is the right tool when one agent makes many calls to the same seller — streaming inference, a data feed, a long-running task. You open once, pay with vouchers, and settle twice on chain (open plus close) regardless of how many calls happen in between. A single seller middleware can advertise both a tab and a one-shot price in the same 402, so tab-native agents and one-shot callers pay at the same rate against the same endpoint.

Tab versus MPP session

Searching the old docs for "tab" used to land you on the MPP sessions page. That is a different package with a different API. If you write against @dexterai/mpp expecting the tab methods on this page, nothing will line up. Pick the primitive first, then read the matching page.

A tab and an MPP session are the same idea: a voucher-signed payment channel you open once, pay against many times, and settle at close. Dexter ships two implementations of that idea in two independent packages, with no dependency between them.

@dexterai/x402/tab (a tab)@dexterai/mpp (a session)
Package@dexterai/x402@dexterai/mpp
Open callopenTab() returns a Tabsession client: deposit, then vouchers
Protocolx402 (Linux Foundation)Machine Payments Protocol (Stripe/Tempo IETF draft)
ChainsSolana vault today; part of a package that also does per-call payments on EVMSolana only
CustodyNon-custodial passkey-rooted vault; only your passkey moves moneyNon-custodial via Swig delegation
Also in the packageReact hooks, browser wallet path, API discovery, per-call paymentsCharge mode (per-request) alongside sessions

Pick a tab when you are already in the x402 world — you use @dexterai/x402 for per-call payments, you want the passkey-vault custody model, or you want one endpoint to serve both tab and one-shot callers. Pick an MPP session when you are building to the MPP draft specifically, or you want MPP's always-on gas sponsorship and its per-request charge mode in the same package.

Both are live on Solana mainnet. This documentation covers the tab. For sessions, see the @dexterai/mpp package README.

Next

On this page