> ## Documentation Index
> Fetch the complete documentation index at: https://docs.livepeer.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Payments

> How ETH moves from gateway to your orchestrator wallet – probabilistic micropayments, winning ticket mechanics, the Redeemer, on-chain redemption on Arbitrum, and keeping your node funded for transactions.

export const CustomDivider = ({color = "var(--lp-color-border-default)", middleText = "", spacing = "default", style = {}, className = "", ...rest}) => {
  const spacingPresets = {
    default: {
      margin: "24px 0"
    },
    overlap: {
      margin: "-1rem 0 -1rem 0"
    },
    tight: {
      margin: "0 0 -1rem 0"
    },
    section: {
      margin: "0 0 -2rem 0"
    },
    sectionOverlap: {
      margin: "-1rem 0 -2rem 0"
    },
    deepOverlap: {
      margin: "-1rem 0 -1.5rem 0"
    }
  };
  const spacingStyle = spacingPresets[spacing] || spacingPresets.default;
  return <div role="separator" aria-orientation="horizontal" className={className} style={{
    display: "flex",
    alignItems: "center",
    ...spacingStyle,
    fontSize: style?.fontSize || "16px",
    height: "fit-content",
    ...style
  }} {...rest}>
      <span style={{
    marginRight: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
      </span>
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      {middleText && <>
          <Icon icon="circle" size={2} />
          <span style={{
    margin: "0 8px",
    fontWeight: "bold",
    color: color,
    opacity: 0.7
  }}>
            {middleText}
          </span>
          <Icon icon="circle" size={2} />
        </>}
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      <span style={{
    marginLeft: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <span style={{
    display: "inline-block",
    transform: "scaleX(-1)"
  }}>
          <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
        </span>
      </span>
    </div>;
};

export const TableCell = ({children, align = "left", header = false, style = {}, className = "", ...rest}) => {
  const Component = header ? "th" : "td";
  return <Component className={className} style={{
    padding: "0.75rem 1rem",
    textAlign: align,
    border: header ? "none" : "1px solid var(--lp-color-border-default)",
    ...style
  }} {...rest}>
      {children}
    </Component>;
};

export const TableRow = ({children, header = false, hover = false, style = {}, className = "", ...rest}) => {
  const rowId = `table-row-${Math.random().toString(36).substr(2, 9)}`;
  return <>
      {hover && <style>{`
          #${rowId}:hover {
            background-color: var(--lp-color-bg-card);
          }
        `}</style>}
      <tr id={rowId} className={className} style={{
    ...header && ({
      backgroundColor: "var(--lp-color-accent-strong)",
      color: "var(--lp-color-on-accent)",
      fontWeight: "bold"
    }),
    ...style
  }} {...rest}>
        {children}
      </tr>
    </>;
};

export const StyledTable = ({children, variant = "default", style = {}, className = "", ...rest}) => {
  const wrapperVariants = {
    default: {
      border: "1px solid var(--lp-color-border-default)",
      backgroundColor: "var(--lp-color-bg-card)",
      overflow: "hidden"
    },
    bordered: {
      border: "2px solid var(--lp-color-accent)",
      backgroundColor: "var(--lp-color-bg-page)",
      overflow: "hidden"
    },
    minimal: {
      border: "none",
      backgroundColor: "transparent",
      overflow: "visible"
    }
  };
  return <div data-docs-styled-table-shell className={className} style={{
    width: "100%",
    padding: 0,
    margin: 0,
    ...wrapperVariants[variant],
    ...style
  }} {...rest}>
      <table data-docs-styled-table style={{
    width: "100%",
    borderCollapse: "collapse",
    borderSpacing: 0,
    margin: 0,
    backgroundColor: "transparent"
  }}>
        {children}
      </table>
    </div>;
};

export const StyledStep = ({title, icon, titleSize = 'h3', iconColor = null, titleColor = null, children, className = '', style = {}, ...rest}) => {
  const styledTitle = titleColor ? <span style={{
    color: titleColor
  }}>{title}</span> : title;
  return <Step title={styledTitle} icon={icon} iconColor={iconColor || undefined} titleSize={titleSize} className={className} style={style} {...rest}>
      {children}
    </Step>;
};

export const StyledSteps = ({children, iconColor, titleColor, lineColor, iconSize = '24px', className = '', style = {}, ...rest}) => {
  const resolvedIconColor = iconColor || 'var(--accent-dark, #18794E)';
  const resolvedTitleColor = titleColor || 'var(--lp-color-accent)';
  const resolvedLineColor = lineColor || 'var(--lp-color-accent)';
  return <div className={['docs-styled-steps', className].filter(Boolean).join(' ')} style={style} {...rest}>
      <style>{`
        .docs-styled-steps .steps > div > div.absolute > div {
          background-color: ${resolvedIconColor};
        }
        .docs-styled-steps .steps > div > div.w-full > p {
          color: ${resolvedTitleColor};
        }
        .docs-styled-steps .steps > div > div.absolute.w-px {
          background-color: ${resolvedLineColor};
        }
        .docs-styled-steps .steps > div:last-child > div.absolute.w-px::after {
          content: '';
          position: absolute;
          bottom: 0;
          left: 50%;
          transform: translateX(-50%);
          width: 6px;
          height: 6px;
          background-color: ${resolvedLineColor};
          transform: translateX(-50%) rotate(45deg);
        }
      `}</style>
      <div>
        <Steps>{children}</Steps>
      </div>
    </div>;
};

Gateways pay Orchestrators in ETH for every job completed through **Probabilistic Micropayments (PM)**. Gateways send lightweight signed tickets, a fraction of which are winners redeemable for a larger ETH payout. This keeps payment traffic efficient even when a node is processing thousands of segments or inference jobs.

Use this page to understand how tickets flow, what makes one a winner, how the Redeemer submits them on-chain, and how to keep your node funded and earning.

<CustomDivider />

## Payment flow overview

```icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
Gateway routes job to your orchestrator
       ↓
You process the job (transcoding segment or AI inference)
       ↓
Gateway attaches a signed payment ticket to the job confirmation
       ↓
Your node evaluates the ticket — is it a winner?
       ↓
Non-winning tickets are discarded
Winning tickets are queued for on-chain submission
       ↓
The Redeemer submits winning tickets to the Arbitrum contract
       ↓
ETH credited to your orchestrator wallet on Arbitrum
       ↓
Your feeShare % flows to your delegators' claimable balance
```

Every step from ticket receipt to on-chain submission happens automatically inside go-livepeer. Keep your node running and maintain enough ETH for gas.

<CustomDivider />

## Probabilistic Micropayments explained

The core idea: the Gateway sends tickets with a small **win probability** instead of settling every segment or inference request on-chain. Each winner is worth a larger amount, and the expected value across many jobs still matches the intended payment total.

```icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
Win probability:       e.g. 1 in 1000
Winning face value:    e.g. 1000 × the per-segment fee
Expected value:        1/1000 × 1000 × fee = fee per segment
```

This means:

* **Only winning tickets trigger on-chain action** – the Redeemer submits winners
* **Winning tickets are infrequent but larger** – each represents many segments' worth of payment
* **Gas costs are batched implicitly** – one redemption transaction covers hundreds or thousands of segments

The result is that a busy Orchestrator usually redeems ETH in a few batched submissions per day. Gas overhead stays negligible relative to earnings.

<Note>
  From a practical perspective, the probabilistic system delivers ETH in larger redemption steps. Balance changes appear when winning tickets are redeemed on-chain, and that stepped pattern is expected behaviour.
</Note>

### Ticket structure

Each payment ticket the Gateway sends contains:

<StyledTable variant="bordered">
  <TableRow header>
    <TableCell header>Field</TableCell>
    <TableCell header>Description</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Face value**</TableCell>
    <TableCell>The ETH amount payable if this ticket wins</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Win probability**</TableCell>
    <TableCell>The probability this ticket is a winner (e.g. `1e-5`)</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Sender address**</TableCell>
    <TableCell>The Gateway's Ethereum address</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Recipient address**</TableCell>
    <TableCell>Your Orchestrator's Ethereum address</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Sender deposit**</TableCell>
    <TableCell>The Gateway's on-chain deposit that backs all their tickets</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Expiry**</TableCell>
    <TableCell>Block number after which this ticket cannot be redeemed</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Signature**</TableCell>
    <TableCell>Gateway's Ethereum signature authorising payment</TableCell>
  </TableRow>
</StyledTable>

Your node verifies the signature, checks the sender has sufficient deposit on-chain to back the ticket, and then evaluates the win condition using a deterministic random function. Winning tickets go to the Redeemer queue.

<CustomDivider />

## The Redeemer

The Redeemer is a component of go-livepeer responsible for submitting winning tickets to the Arbitrum smart contract.

In a standard single-node setup, the Redeemer runs as part of your Orchestrator process. Multi-node or high-volume setups often run the Redeemer as a separate service to centralise on-chain redemption across multiple worker nodes.

### What the Redeemer does

```icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
Winning ticket received from PM evaluator
       ↓
Redeemer batches pending winning tickets
       ↓
Redeemer submits batch transaction to Arbitrum PM contract
       ↓
Contract verifies: valid signature, sufficient sender deposit, not expired
       ↓
ETH transferred from gateway's deposit to your wallet
```

### Gas requirements for redemption

Redemption transactions run on Arbitrum One (L2). Gas costs are low, but your wallet must hold ETH on Arbitrum:

<StyledTable variant="bordered">
  <TableRow header>
    <TableCell header>Factor</TableCell>
    <TableCell header>Value</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>Gas per redemption transaction</TableCell>
    <TableCell>\~100,000 – 200,000 gas</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>Typical Arbitrum gas price</TableCell>
    <TableCell>0.01 – 0.1 gwei</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>Approximate ETH cost per redemption</TableCell>
    <TableCell>\~$0.01 – $0.05 USD</TableCell>
  </TableRow>
</StyledTable>

Keep a minimum of **0.01 ETH on Arbitrum** in your Orchestrator wallet to prevent redemption failures. A depleted wallet means winning tickets expire unsubmitted – that ETH is permanently lost.

<Warning>
  A wallet without ETH on Arbitrum lets winning tickets expire before redemption. The Gateway's deposit stays intact, and the loss sits entirely with your node. Monitor your ETH balance and top it up regularly. See [Funding Your Node](#funding-your-node) below.
</Warning>

<CustomDivider />

## Video vs AI payment differences

The probabilistic payment system is the same for both workload types, but the fee structure differs:

<AccordionGroup>
  <Accordion title="Video transcoding payments" icon="video">
    Transcoding is paid per segment – approximately every 2 seconds of video processed.

    * **Pricing unit:** per segment (or per pixel, depending on configuration)
    * **Job frequency:** continuous for active live streams
    * **Payment trigger:** one ticket per segment delivered
    * **Selection factor:** stake-weighted routing; higher total stake = more segments routed to you
    * **Typical fee level:** low per-segment (highly competitive, commoditised pipeline)

    The transcoding fee rate is set by your `-pricePerUnit` flag in Wei per pixel. Gateways filter Orchestrators by maximum acceptable price before routing.
  </Accordion>

  <Accordion title="AI inference payments" icon="microchip">
    AI inference is paid per inference job – one ticket per job request.

    * **Pricing unit:** per output pixel (image pipelines), per ms of audio (audio-to-text), per token (LLM), or per frame (live video)
    * **Job frequency:** per-request bursts
    * **Payment trigger:** one ticket per completed inference job
    * **Selection factor:** capability first, price second; stake weight is a secondary factor
    * **Typical fee level:** higher per-job than transcoding (GPU-intensive work)

    AI fees are configured in `aiModels.json` via the `price_per_unit` field. The pricing unit varies by pipeline – see [Model and VRAM Reference](/v2/Orchestrators/guides/ai-and-job-workloads/model-demand-reference) for per-pipeline pricing units.
  </Accordion>

  <Accordion title="Live AI (Cascade) payments" icon="microchip">
    Live-video AI (live-video-to-video) uses a time-based payment model measured across the active stream session.

    * **Pricing unit:** per second of active stream
    * **Payment trigger:** periodic PM tickets at regular intervals during the stream session
    * **Payment state:** the Gateway maintains running session state to calculate fees based on elapsed time
    * **Relevance to remote signers:** Live AI payment state is managed by the remote signer component (PRs #3791 and #3822). See [Remote Signers](/v2/Gateways/guides/payments-and-pricing/remote-signers) for Gateway-side context.
  </Accordion>
</AccordionGroup>

<CustomDivider />

## Clearinghouses

In the standard PM model, the Gateway itself holds an Ethereum deposit on-chain and signs payment tickets directly. A **clearinghouse** is an alternative arrangement where a third-party operator manages the PM deposit and ticket signing on behalf of Gateways that don't want to handle crypto infrastructure directly.

From the Orchestrator's perspective, payments from a Gateway using a clearinghouse are identical to direct PM payments. The same ticket structure, the same Redeemer process, the same Arbitrum redemption.

Clearinghouses exist to enable:

* Gateway implementations on platforms that can't easily handle Ethereum keys (browser, mobile)
* Enterprise Gateways that want to settle in fiat while still using Livepeer Orchestrators
* Separation of media processing concerns from payment logistics

This is a Gateway-side concern. You receive valid signed tickets and redeem them – the clearinghouse arrangement is transparent to you.

For the Gateway-side detail, see [Payment Clearinghouses](/v2/Gateways/guides/payments-and-pricing/clearinghouse-guide).

<CustomDivider />

## Funding your node

Your Orchestrator wallet on Arbitrum needs ETH for three types of transaction:

<StyledTable variant="bordered">
  <TableRow header>
    <TableCell header>Transaction type</TableCell>
    <TableCell header>Approximate ETH needed</TableCell>
    <TableCell header>Frequency</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>Reward() call</TableCell>
    <TableCell>\~0.000005 – 0.00005 ETH per round</TableCell>
    <TableCell>Once per round (\~22h)</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>Ticket redemption</TableCell>
    <TableCell>\~0.00002 – 0.0001 ETH per batch</TableCell>
    <TableCell>Multiple times daily at volume</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>Activation / re-registration</TableCell>
    <TableCell>\~0.0001 ETH one-time</TableCell>
    <TableCell>Rare</TableCell>
  </TableRow>
</StyledTable>

**Recommended minimum balance:** 0.01 ETH on Arbitrum. Replenish when you fall below 0.005 ETH.

### Bridging ETH to Arbitrum

Bridge ETH from Ethereum mainnet to Arbitrum One when your operating wallet starts on L1:

<StyledSteps>
  <StyledStep title="Use the Arbitrum official bridge">
    Go to [bridge.Arbitrum.io](https://bridge.arbitrum.io) and connect the wallet corresponding to your Orchestrator address.
  </StyledStep>

  <StyledStep title="Bridge ETH from L1 to Arbitrum One">
    Select Ethereum → Arbitrum One. Enter the amount to bridge. Bridging takes approximately 15 minutes for the deposit to confirm on Arbitrum.
  </StyledStep>

  <StyledStep title="Verify receipt on Arbitrum">
    Check [Arbiscan.io](https://arbiscan.io) for your Orchestrator address to confirm the ETH arrived.
  </StyledStep>

  <StyledStep title="Set up balance monitoring">
    Add your Orchestrator wallet address to a balance monitoring tool. Alert when balance drops below your threshold. Most operators use Prometheus + Grafana for this – see [Metrics and Monitoring](/v2/Orchestrators/guides/monitoring-and-tooling/metrics-and-alerting).
  </StyledStep>
</StyledSteps>

ETH is also available on Arbitrum directly from centralised exchanges that support Arbitrum One withdrawals (Binance, Coinbase, Kraken). Check current exchange support before withdrawing.

<CustomDivider />

## Checking payment health

The go-livepeer node exposes Prometheus metrics for payment activity. Key ones to watch:

<StyledTable variant="bordered">
  <TableRow header>
    <TableCell header>Metric</TableCell>
    <TableCell header>What it shows</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>`livepeer_pm_winning_tickets_received`</TableCell>
    <TableCell>Winning tickets your node has validated</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>`livepeer_pm_winning_tickets_redeemed`</TableCell>
    <TableCell>Tickets successfully submitted on-chain</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>`livepeer_pm_ticket_redemption_errors`</TableCell>
    <TableCell>Failed redemptions (often ETH balance or network issues)</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>`livepeer_eth_balance`</TableCell>
    <TableCell>Your current Orchestrator ETH balance on Arbitrum</TableCell>
  </TableRow>
</StyledTable>

A healthy node has `tickets_redeemed` tracking closely behind `tickets_received`, and zero sustained `redemption_errors`. Persistent errors with `redemption_errors > 0` usually indicate a depleted ETH balance or a connectivity issue with your Arbitrum RPC endpoint.

For the complete Prometheus metric reference, see [Metrics and Monitoring](/v2/Orchestrators/guides/monitoring-and-tooling/metrics-and-alerting).

<CustomDivider />

## Related

<CardGroup cols={2}>
  <Card title="Earnings Explained" icon="chart-line" href="/v2/orchestrators/guides/staking-and-rewards/earning-model">
    The full picture: both revenue streams, commission parameters, and what determines job wins.
  </Card>

  <Card title="Rewards and Fees" icon="hand-holding-dollar" href="/v2/orchestrators/guides/staking-and-rewards/reward-mechanics">
    LPT reward calling, gas thresholds, and setting commission via livepeer\_cli.
  </Card>

  <Card title="Payment Clearinghouses" icon="building-columns" href="/v2/gateways/guides/payments-and-pricing/clearinghouse-guide">
    Gateway-side clearinghouse model and off-chain settlement options.
  </Card>

  <Card title="Remote Signers" icon="key" href="/v2/gateways/guides/payments-and-pricing/remote-signers">
    How Live AI payment state is managed for off-chain Gateway implementations.
  </Card>
</CardGroup>
