> ## 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.

# Gateway access for developers

> Three ways to access the Livepeer network as a developer: the community gateway (free, no setup), a managed gateway provider (API key), and a self-hosted go-livepeer gateway (full control).

export const CenteredContainer = ({children, maxWidth = "800px", padding = "0", preset = "default", width = "", minWidth = "", marginRight = "", marginBottom = "", textAlign = "", style = {}, className = "", ...rest}) => {
  const presets = {
    default: {},
    fitContent: {
      width: "fit-content",
      minWidth: "fit-content"
    },
    readable70: {
      width: "70%",
      minWidth: "fit-content"
    },
    readable80: {
      width: "80%",
      minWidth: "fit-content"
    },
    readable90: {
      width: "90%"
    },
    wide900: {
      maxWidth: "900px"
    }
  };
  const presetStyle = presets[preset] || presets.default;
  return <div className={className} style={{
    maxWidth: presetStyle.maxWidth || maxWidth,
    margin: "0 auto",
    padding: padding,
    ...presetStyle.width ? {
      width: presetStyle.width
    } : {},
    ...presetStyle.minWidth ? {
      minWidth: presetStyle.minWidth
    } : {},
    ...width ? {
      width
    } : {},
    ...minWidth ? {
      minWidth
    } : {},
    ...marginRight ? {
      marginRight
    } : {},
    ...marginBottom ? {
      marginBottom
    } : {},
    ...textAlign ? {
      textAlign
    } : {},
    ...style
  }} {...rest}>
      {children}
    </div>;
};

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>;
};

<CenteredContainer preset="readable90">
  <Tip>Most developers never need to run a Gateway. The community Gateway handles development; a managed Gateway provider handles production. Self-host only when you need pricing control, data residency, or custom Orchestrator routing.</Tip>
</CenteredContainer>

<CustomDivider />

A Gateway is the node that routes your AI inference or video transcoding requests to Orchestrators on the Livepeer Network. Every request to the network goes through a Gateway. The question is whose Gateway you use.

<CustomDivider />

## Access levels

<StyledTable variant="bordered">
  <thead>
    <TableRow header>
      <TableCell header>Level</TableCell>
      <TableCell header>Gateway</TableCell>
      <TableCell header>Auth</TableCell>
      <TableCell header>Cost</TableCell>
      <TableCell header>Control</TableCell>
    </TableRow>
  </thead>

  <tbody>
    <TableRow>
      <TableCell>**Development**</TableCell>
      <TableCell>Community Gateway (`dream-gateway.livepeer.cloud`)</TableCell>
      <TableCell>None</TableCell>
      <TableCell>Free</TableCell>
      <TableCell>None (shared infrastructure, no SLA)</TableCell>
    </TableRow>

    <TableRow>
      <TableCell>**Production (managed)**</TableCell>
      <TableCell>Gateway provider with API key</TableCell>
      <TableCell>Bearer token</TableCell>
      <TableCell>Provider pricing (includes margin)</TableCell>
      <TableCell>Provider controls routing; you control request volume</TableCell>
    </TableRow>

    <TableRow>
      <TableCell>**Production (self-hosted)**</TableCell>
      <TableCell>go-livepeer in broadcaster mode</TableCell>
      <TableCell>Your own auth layer</TableCell>
      <TableCell>Direct Orchestrator settlement (no margin)</TableCell>
      <TableCell>Full: Orchestrator selection, pricing, failover, auth model</TableCell>
    </TableRow>
  </tbody>
</StyledTable>

<CustomDivider />

## Community Gateway

The community Gateway at `dream-gateway.livepeer.cloud` is operated by the Cloud SPE for development access. It accepts unauthenticated requests and routes to the active Orchestrator set.

```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
curl -X POST https://dream-gateway.livepeer.cloud/text-to-image \
  -H "Content-Type: application/json" \
  -d '{"prompt": "a mountain at dawn", "model_id": "SG161222/RealVisXL_V4.0_Lightning"}'
```

The community Gateway is shared infrastructure with no SLA. It is rate-limited for sustained high-volume traffic. Do not ship user-facing production applications on the community Gateway.

**When to use:** prototyping, integration testing, first inference call, tutorials.

<CustomDivider />

## Managed Gateway provider

A managed Gateway provider gives you an API key and a Gateway endpoint. Requests are authenticated, rate-limited per your tier, and the provider handles Orchestrator routing and payment settlement.

```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
curl -X POST https://provider-gateway.example.com/text-to-image \
  -H "Authorization: Bearer $LIVEPEER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "a mountain at dawn", "model_id": "SG161222/RealVisXL_V4.0_Lightning"}'
```

The request shape is identical to the community Gateway. Switching from community to managed requires changing the base URL and adding the `Authorization` header.

**When to use:** production applications where you want no infrastructure overhead and accept the provider's pricing and routing decisions.

<CustomDivider />

## Self-hosted Gateway

Running go-livepeer in broadcaster mode gives direct network access. You control which Orchestrators receive your jobs, what price you pay per unit, and how authentication works.

```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
livepeer \
  -broadcaster \
  -network arbitrum-one-mainnet \
  -ethUrl <ARBITRUM_RPC_URL> \
  -ethKeystorePath ~/.lpData/arbitrum-one-mainnet/keystore \
  -maxPricePerUnit 0 \
  -rtmpAddr 127.0.0.1:1935 \
  -httpAddr 127.0.0.1:8935
```

Self-hosted Gateways require:

| Requirement           | AI Gateway (off-chain)            | Video Gateway (on-chain)                     |
| --------------------- | --------------------------------- | -------------------------------------------- |
| Operating system      | Linux (or Docker)                 | Linux                                        |
| ETH on Arbitrum One   | Not required for off-chain mode   | Required (TicketBroker deposit)              |
| go-livepeer binary    | Required                          | Required                                     |
| Orchestrator list     | At least one `-orchAddr` endpoint | Network discovery via on-chain registry      |
| Open port             | Port 8935 (default)               | Port 8935 (default)                          |
| Time to first request | \~15 minutes with Docker          | Longer (ETH account setup + deposit funding) |

<Warning>
  Self-hosted AI Gateways require Linux. Windows and macOS binaries for go-livepeer with AI support are not currently available.
</Warning>

**When to use:** your monthly API spend is material, you need to specify which Orchestrators handle your jobs, you need the inference path to stay within your own infrastructure, or you need a custom auth/billing model.

<CustomDivider />

## Self-hosting decision

The natural path for most developers: start with the community Gateway, build and validate your application, move to a managed provider for production, then self-host as usage grows and the cost or control trade-offs become worth the overhead.

| Signal                                    | Action                                                                        |
| ----------------------------------------- | ----------------------------------------------------------------------------- |
| First inference call, prototyping         | Stay on community Gateway                                                     |
| Shipping to users, need reliability       | Move to managed provider                                                      |
| Monthly spend is material                 | Evaluate self-hosting for direct settlement                                   |
| Need custom Orchestrator routing          | Self-host                                                                     |
| Data must stay within your infrastructure | Self-host                                                                     |
| Need custom auth or per-user billing      | Self-host + [pymthouse](/v2/developers/guides/payments/clearinghouse-pattern) |

There is no hard threshold at which you must switch. The signals are cost, control, and data residency.

<CustomDivider />

## Orchestrator session lifecycle

When a Gateway receives a job, it selects an Orchestrator from its candidate list (explicit `-orchAddr` or network discovery), sends a `GetOrchestratorInfo` request, negotiates capabilities and pricing, and routes the job. For live AI (`live-video-to-video`), the session persists for the stream duration; the Gateway routes all frames to the same Orchestrator until the session ends or the Orchestrator fails.

For batch jobs, each request may go to a different Orchestrator. The Gateway applies stake-weighted selection with price filtering for each request independently.

Session management is automatic in go-livepeer. For custom Gateway implementations, the `livepeer-python-gateway` reference implementation exposes the session lifecycle through `OrchestratorSession` and `SelectionCursor` classes. See [alt-Gateways](/v2/developers/build/alt-Gateways/overview) for the Python Gateway architecture.

<CustomDivider />

The [local Gateway setup](/v2/developers/guides/local-development/local-Gateway) walks through running a self-hosted broadcaster node step by step. The [production checklist](/v2/developers/guides/production-hardening-checklist) covers what to verify before moving to real traffic.
