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

# Publishing a Gateway

> Make a Livepeer Gateway discoverable - service URI configuration, DNS setup, capability advertising, community presence, and current discoverability options.

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

export const BorderedBox = ({children, variant = "default", padding = "var(--lp-spacing-4)", borderRadius = "var(--lp-spacing-px-8)", margin = "", accentBar = "", style = {}, className = "", ...rest}) => {
  const variants = {
    default: {
      border: "1px solid var(--lp-color-border-default)",
      backgroundColor: "var(--lp-color-bg-card)"
    },
    accent: {
      border: "1px solid var(--lp-color-accent)",
      backgroundColor: "var(--lp-color-bg-card)"
    },
    muted: {
      border: "1px solid var(--lp-color-border-default)",
      backgroundColor: "transparent"
    }
  };
  const accentBarColors = {
    accent: "var(--lp-color-accent)",
    positive: "var(--green-9)"
  };
  return <div data-docs-bordered-box="" data-accent-bar={accentBarColors[accentBar] ? "" : undefined} className={className} style={{
    ...variants[variant],
    padding: padding,
    borderRadius: borderRadius,
    ...margin ? {
      margin
    } : {},
    ...accentBarColors[accentBar] ? {
      position: "relative",
      '--accent-bar-color': accentBarColors[accentBar]
    } : {},
    ...style
  }} {...rest}>
      {children}
    </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 LinkArrow = ({href, label, description, newline = true, borderColor, className = '', style = {}, ...rest}) => {
  const linkArrowStyle = {
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    gap: "var(--lp-spacing-1)",
    width: 'fit-content',
    ...borderColor && ({
      borderColor
    })
  };
  return <span className={className} style={style} {...rest}>
      {newline && <br />}
      <span style={linkArrowStyle}>
        <a href={href} target="_blank" rel="noopener noreferrer">
          {label}
        </a>
        <Icon icon="arrow-up-right" size={14} color="var(--lp-color-accent)" />
      </span>
      {description && description}
      {description && <div style={{
    height: "var(--lp-spacing-3)"
  }} />}
    </span>;
};

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

<Tip>
  AI Gateways can register on-chain via the [`AIServiceRegistry`](https://arbiscan.io/address/0x04C0b249740175999E5BF5c9ac1dA92431EF34C5) contract using the `-aiServiceRegistry` flag. Video/transcoding Gateways do not yet have an equivalent on-chain registry - discoverability for video is currently manual and community-driven.

  A Gateway Explorer Page is in Development: <LinkArrow label="Gateway Explorer Preview" href="https://explorer-arbitrum-one-git-feat-add-g-10dba1-livepeer-foundation.vercel.app/" /><LinkArrow label="Github PR #410" href="https://github.com/livepeer/explorer/pull/410" />
</Tip>

<CustomDivider style={{margin: "-1rem 0 -1rem 0"}} />

how to make a Gateway reachable and findable, so that other developers and applications can discover and use it.

<StyledSteps>
  <StyledStep icon="satellite-dish">
    ### Service URI

    The first requirement is that the Gateway is reachable at a stable, public address.

    ```bash icon="terminal" -serviceAddr theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -serviceAddr gateway.example.com:8935
    ```

    `-serviceAddr` tells the Gateway what address to advertise. For a public Gateway, this must be an externally resolvable DNS name and port, not `localhost` or an internal IP.

    For the external hostname used in responses:

    ```bash icon="terminal" -gatewayHost theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    -gatewayHost gateway.example.com
    ```

    <CustomDivider style={{margin: "-2.5rem auto -2rem auto", width: "50%"}} />
  </StyledStep>

  <StyledStep icon="signature">
    ### DNS setup

    Point a dedicated subdomain at the Gateway server's public IP. A dedicated subdomain (instead of an IP address) allows changing servers without updating customer integrations.

    ```txt icon="wrench" DNS Setup theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    ai-gateway.yourdomain.com.   A   <server-ip>
    ```

    For multi-region deployments, use GeoDNS or a load balancer DNS record that routes to the nearest region.

    <CustomDivider style={{margin: "-2rem auto -2rem auto", width: "50%"}} />
  </StyledStep>

  <StyledStep icon="wifi">
    ### HTTPS required

    External clients must reach the Gateway over HTTPS. Set up TLS termination via a reverse proxy (Caddy, Nginx, or a cloud load balancer) before exposing the service. See <LinkArrow href="/v2/gateways/guides/advanced-operations/gateway-middleware" label="Gateway Middleware" newline={false} /> for reverse proxy architecture patterns.
  </StyledStep>
</StyledSteps>

<CustomDivider style={{margin: "-1rem 0 -2rem 0"}} />

## Capability Advertising

Developers choosing a Gateway need to know what it supports. There is no standard machine-readable format for this yet, but publishing a clear capabilities document on the domain is current best practice.

<AccordionGroup>
  <Accordion title="Supported workloads" icon="list-check">
    State explicitly whether the Gateway handles:

    * AI inference (and which pipelines: text-to-image, image-to-video, LLM, etc.)
    * Video transcoding
    * Live AI (video-to-video)
    * BYOC pipelines

    For AI inference, list the models available via connected Orchestrators. Generate this dynamically from the Gateway's `/getNetworkCapabilities` endpoint:

    ```bash icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
    curl https://gateway.example.com/getNetworkCapabilities | \
      jq '[.orchestrators[].capabilities_prices[].model_id] | unique'
    ```
  </Accordion>

  <Accordion title="Pricing" icon="tag">
    Publish customer-facing pricing. The Gateway has two pricing layers:

    * What it pays Orchestrators (`-maxPricePerCapability`, `-maxPricePerUnit`) - the cost floor
    * What it charges customers - the business decision

    These do not need to match. Most public Gateways add a margin and present pricing in human-readable units (per image, per minute of video) instead of in wei per pixel.
  </Accordion>

  <Accordion title="Authentication" icon="key">
    Describe how developers authenticate: API key, OAuth, or open access. If registration is required, link to the signup page.
  </Accordion>

  <Accordion title="Rate limits and SLAs" icon="gauge-high">
    Document any rate limits and what SLA is offered. Even a best-effort statement ("target 99% uptime") sets expectations and builds trust.
  </Accordion>
</AccordionGroup>

<CustomDivider style={{margin: "0 0 -2rem 0"}} />

## Discovery Methods

These are the mechanisms developers use today to find public Gateways.

<BorderedBox variant="accent">
  <Tabs>
    <Tab title="Community" icon="comments">
      The most effective current method. Announce the Gateway in the [Livepeer Discord](https://discord.gg/livepeer) in the `#local-gateways` channel. Include:

      * Gateway endpoint URL
      * Supported pipelines and models
      * Pricing and any access requirements
      * Operating region(s)

      The Forum at [forum.livepeer.org](https://forum.livepeer.org) is appropriate for longer announcements with more detail, and threads are indexed by search engines.
    </Tab>

    <Tab title="Livepeer Tools" icon="gauge-high">
      [tools.Livepeer.cloud](https://tools.livepeer.cloud) is a community-maintained dashboard that tracks active network participants. Contact the maintainers to have the Gateway listed.
    </Tab>

    <Tab title="Providers directory" icon="list">
      The Foundation maintains a list of known public Gateways in the Gateway Providers page. Contact the Foundation to have the Gateway added.

      SPE-funded Gateways (Livepeer Cloud, Daydream) are listed automatically as part of their SPE agreement.
    </Tab>

    <Tab title="Direct integration" icon="plug">
      For developers building applications, the most common path is direct integration: they find the Gateway through one of the channels above and hardcode the endpoint. Make it easy by providing:

      * A clear API reference (the Gateway endpoint + the standard <LinkArrow href="/v2/gateways/resources/reference/technical/api-reference/AI-API/ai" label="AI API reference" newline={false} />)
      * A working quickstart curl command
      * A stable versioned endpoint URL
    </Tab>
  </Tabs>
</BorderedBox>

<CustomDivider style={{margin: "0 0 -2rem 0"}} />

## Marketplace Context

The Livepeer Marketplace is a programmatic interface for Orchestrators to advertise compute and for Gateways to discover and route to that compute. It is not a discovery mechanism for applications to find Gateways.

As a Gateway operator, the relationship to the marketplace is as a **broker**: the Gateway queries it to find Orchestrators, not to list itself for applications to find. The marketplace is upstream of the Gateway, not downstream.

```icon="terminal" theme={"theme":{"light":"github-light","dark":"dark-plus"}}
Applications -> [Gateway] -> Marketplace -> Orchestrators
```

There is currently no Gateway layer in the marketplace. On-chain Gateway registration (equivalent to how Orchestrators register via ServiceRegistry) is on the roadmap but not yet available.

<CustomDivider style={{margin: "-1rem 0 -2rem 0"}} />

## Video Gateways

<Badge color="blue"> Video </Badge>

Video Gateways use `-serviceAddr` differently from AI Gateways. For a Video Gateway, `-serviceAddr` is the address that the Gateway advertises to Orchestrators so they can report results back. It must be reachable by Orchestrators on the network.

This means the Video Gateway's service address must be publicly reachable on the Gateway's HTTP port (default 8935). If behind NAT, configure port forwarding or use a server with a public IP.

RTMP ingest (port 1935) is separate from the service address and is what video sources connect to. These can be on different ports or even different network interfaces.

<CustomDivider style={{margin: "-1rem 0 -2rem 0"}} />

## On-chain Discovery

<BorderedBox variant="accent">
  <Tabs>
    <Tab title="AI Registry" icon="brain">
      <Badge color="purple">AI</Badge>   <Badge color="green">Dual</Badge>

      The `-aiServiceRegistry` flag enables on-chain discovery for AI Gateways. When set, the Gateway registers with the [`AIServiceRegistry`](https://arbiscan.io/address/0x04C0b249740175999E5BF5c9ac1dA92431EF34C5) contract on Arbitrum Mainnet, making it discoverable by AI Orchestrators on-chain.

      ### Usage

      Add `-aiServiceRegistry` to the Gateway startup command alongside the on-chain flags:

      ```bash icon="terminal" -aiServiceRegistry theme={"theme":{"light":"github-light","dark":"dark-plus"}}
      livepeer \
      -gateway \
      -aiServiceRegistry \
      -network arbitrum-one-mainnet \
      -ethUrl https://arb1.arbitrum.io/rpc \
      -ethKeystorePath ~/.lpData/keystore \
      -httpAddr 0.0.0.0:8935 \
      -httpIngest \
      ...
      ```

      ### What it does

      * Registers the Gateway's AI capabilities with the on-chain `AIServiceRegistry` contract
      * Enables automatic Orchestrator discovery for AI workloads (no need for manual `-orchAddr` lists)
      * Requires on-chain operational mode (`-network=arbitrum-one-mainnet`, `-ethUrl`, funded ETH account)

      ### When to use it

      Use `-aiServiceRegistry` when the Gateway should discover AI Orchestrators from the open network instead of relying on a manually curated `-orchAddr` list. This is the on-chain equivalent of off-chain manual discovery.

      Without this flag, the Gateway operates off-chain and requires explicit Orchestrator addresses via `-orchAddr`.
    </Tab>

    <Tab title="Video Registry" icon="video">
      <Badge color="yellow">Planned</Badge>   <Badge color="blue">Video</Badge>

      There is no equivalent of the Orchestrator `ServiceRegistry` for transcoding Gateways. Orchestrators register on-chain via `ServiceRegistry` and appear in the Livepeer Explorer automatically, but transcoding Gateways cannot register in the same way.

      On-chain Gateway registration for the transcoding network is on the roadmap but not yet available. Until it ships, Video and Dual Gateways rely on the community channels and manual listing methods described in the Discovery Methods section above.
    </Tab>
  </Tabs>
</BorderedBox>

<CustomDivider style={{margin: "0 0 -2rem 0"}} />

## Related Pages

<CardGroup cols={2}>
  <Card title="Gateway Middleware" icon="layer-group" href="/v2/gateways/guides/advanced-operations/gateway-middleware">
    Auth and routing - prerequisites for a public-facing Gateway.
  </Card>

  <Card title="Opportunities" icon="lightbulb" href="/v2/gateways/guides/roadmap-and-funding/operator-support">
    Revenue models and Foundation support for Gateway operators.
  </Card>

  <Card title="NaaP Multi-Tenancy" icon="users" href="/v2/gateways/guides/roadmap-and-funding/naap-multi-tenancy">
    Network as a Platform architecture for multi-tenant operation.
  </Card>

  <Card title="Technical Architecture" icon="diagram-project" href="/v2/gateways/resources/reference/technical/technical-architecture">
    Network architecture context for how Gateways fit into the ecosystem.
  </Card>
</CardGroup>
