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

# Ports

> Expose a port on a Dedalus Machine over a public HTTPS URL

export const Callout = ({icon = "lightbulb", iconJsx, color = "default", children}) => {
  const [isDark, setIsDark] = useState(false);
  useEffect(() => {
    const probe = () => setIsDark(document.documentElement.classList.contains("dark"));
    probe();
    const obs = new MutationObserver(probe);
    obs.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ["class"]
    });
    return () => obs.disconnect();
  }, []);
  const palette = {
    default: {
      bg: isDark ? "rgba(39, 39, 42, 0.6)" : "rgb(244, 244, 245)",
      fg: isDark ? "rgb(228, 228, 231)" : "rgb(39, 39, 42)"
    },
    brand: {
      bg: isDark ? "rgba(76, 29, 149, 0.2)" : "rgb(245, 243, 255)",
      fg: isDark ? "rgb(221, 214, 254)" : "rgb(76, 29, 149)"
    },
    info: {
      bg: isDark ? "rgba(30, 58, 138, 0.2)" : "rgb(239, 246, 255)",
      fg: isDark ? "rgb(191, 219, 254)" : "rgb(30, 58, 138)"
    },
    success: {
      bg: isDark ? "rgba(20, 83, 45, 0.2)" : "rgb(240, 253, 244)",
      fg: isDark ? "rgb(187, 247, 208)" : "rgb(20, 83, 45)"
    },
    warning: {
      bg: isDark ? "rgba(120, 53, 15, 0.2)" : "rgb(255, 251, 235)",
      fg: isDark ? "rgb(253, 230, 138)" : "rgb(120, 53, 15)"
    },
    danger: {
      bg: isDark ? "rgba(127, 29, 29, 0.2)" : "rgb(254, 242, 242)",
      fg: isDark ? "rgb(254, 202, 202)" : "rgb(127, 29, 29)"
    }
  };
  const tint = palette[color] ?? palette.default;
  const lucide = {
    "lightbulb": <>
				<path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5" />
				<path d="M9 18h6" />
				<path d="M10 22h4" />
			</>,
    "info": <>
				<circle cx="12" cy="12" r="10" />
				<path d="M12 16v-4" />
				<path d="M12 8h.01" />
			</>,
    "alert-triangle": <>
				<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z" />
				<path d="M12 9v4" />
				<path d="M12 17h.01" />
			</>,
    "alert-octagon": <>
				<polygon points="7.86 2 16.14 2 22 7.86 22 16.14 16.14 22 7.86 22 2 16.14 2 7.86 7.86 2" />
				<line x1="12" y1="8" x2="12" y2="12" />
				<line x1="12" y1="16" x2="12.01" y2="16" />
			</>,
    "check-circle": <>
				<path d="M21.801 10A10 10 0 1 1 17 3.335" />
				<path d="m9 11 3 3L22 4" />
			</>,
    "x-circle": <>
				<circle cx="12" cy="12" r="10" />
				<path d="m15 9-6 6" />
				<path d="m9 9 6 6" />
			</>,
    "sparkles": <>
				<path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z" />
				<path d="M20 3v4" />
				<path d="M22 5h-4" />
				<path d="M4 17v2" />
				<path d="M5 18H3" />
			</>,
    "code": <>
				<polyline points="16 18 22 12 16 6" />
				<polyline points="8 6 2 12 8 18" />
			</>,
    "terminal": <>
				<polyline points="4 17 10 11 4 5" />
				<line x1="12" y1="19" x2="20" y2="19" />
			</>,
    "book-open": <>
				<path d="M12 7v14" />
				<path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z" />
			</>,
    "zap": <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />,
    "clock": <>
				<circle cx="12" cy="12" r="10" />
				<polyline points="12 6 12 12 16 14" />
			</>
  };
  let resolvedIcon;
  if (iconJsx !== undefined) {
    resolvedIcon = iconJsx;
  } else {
    const paths = lucide[icon];
    if (!paths) {
      throw new Error(`<Callout icon="${icon}"> is not a known Lucide name. ` + `Either add it to the lucide table in callout.jsx, or pass iconJsx={...} for custom JSX. ` + `Available: ${Object.keys(lucide).join(", ")}`);
    }
    resolvedIcon = <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
				{paths}
			</svg>;
  }
  return <div className="flex items-start gap-3 px-4 py-3 my-4" style={{
    backgroundColor: tint.bg,
    color: tint.fg
  }}>
			<span className="leading-none mt-[3px] shrink-0 select-none [&>svg]:block">{resolvedIcon}</span>
			<div className="flex-1 min-w-0 [&>*:first-child]:mt-0 [&>*:last-child]:mb-0 [&_a_code]:no-underline [&_a]:underline-offset-[3px]">
				{children}
			</div>
		</div>;
};

<CodeGroup>
  ```bash CLI theme={"theme":{"light":"github-light","dark":"github-dark"}}
  dedalus machines ports create \
    --machine-id <machine_id> \
    --port 3000 \
    --protocol https \
    --visibility public
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  p = client.machines.ports.create(
      machine_id="<machine_id>",
      port=3000,
      protocol="https",
      visibility="public",
  )
  print(p.url)  # https://<id>.preview.dedaluslabs.ai
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  const p = await client.machines.ports.create({
    machine_id: "<machine_id>",
    port: 3000,
    protocol: "https",
    visibility: "public",
  });
  console.log(p.url);
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"github-dark"}}
  p, _ := client.Machines.Ports.New(ctx, dedalus.MachinePreviewNewParams{
      MachineID: machineID,
      PreviewCreateParams: dedalus.PreviewCreateParams{
          Port:       3000,
          Protocol:   dedalus.PreviewCreateParamsProtocolHTTPS,
          Visibility: dedalus.PreviewCreateParamsVisibilityPublic,
      },
  })
  fmt.Println(p.URL)
  ```
</CodeGroup>

Creates a public URL that proxies to a port inside the machine. Pass the port your service listens on; use the returned `url` to open it from a browser or webhook provider.

<Accordion title="Parameters">
  <ParamField path="machine_id" type="string" required>
    The machine that runs the service.
  </ParamField>

  <ParamField body="port" type="integer" required>
    The internal port your service listens on.
  </ParamField>

  <ParamField body="protocol" default="https" type="string">
    Public protocol for the exposed URL.
  </ParamField>

  <ParamField body="visibility" default="public" type="string">
    Who can use the URL: `public`, `org`, or `private`.
  </ParamField>
</Accordion>

## Manage exposed ports

<CodeGroup>
  ```bash CLI theme={"theme":{"light":"github-light","dark":"github-dark"}}
  dedalus machines ports list --machine-id <machine_id>
  dedalus machines ports retrieve --machine-id <machine_id> --port-id <port_id>
  dedalus machines ports delete --machine-id <machine_id> --port-id <port_id>
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  ```

  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  await client.machines.previews.list({ machine_id: "<machine_id>" });
  await client.machines.previews.retrieve({
    machine_id: "<machine_id>",
    preview_id: "<preview_id>",
  });
  await client.machines.previews.delete({
    machine_id: "<machine_id>",
    preview_id: "<preview_id>",
  });
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"github-dark"}}
  client.Machines.Previews.List(ctx, dedalus.MachinePreviewListParams{
      MachineID: machineID,
  })
  client.Machines.Previews.Get(ctx, dedalus.MachinePreviewGetParams{
      MachineID:  machineID,
      PreviewID: "<preview_id>",
  })
  client.Machines.Previews.Delete(ctx, dedalus.MachinePreviewDeleteParams{
      MachineID:  machineID,
      PreviewID: "<preview_id>",
  })
  ```
</CodeGroup>

<Accordion title="Parameters">
  <ParamField path="machine_id" type="string" required>
    The machine that owns the exposed port.
  </ParamField>

  <ParamField path="preview_id" type="string" required>
    The preview resource to retrieve or delete.
  </ParamField>
</Accordion>
