# .NET Quickstart

> Create a live input, push a broadcast, in C#.

## 1. Install

```bash
dotnet add package ClutchCall.SDK
```

## 2. Create a live input + mint a playback URL

```csharp
using ClutchCall.SDK;

var s = new Streams(
    baseUrl: "https://app.clutchcall.dev",
    apiKey:  Environment.GetEnvironmentVariable("CLUTCHCALL_API_KEY"),
    orgId:   "org_abc");

var created = await s.LiveInputs.CreateAsync(new Streams.CreateLiveInput {
    Name = "My First Stream",
});
Console.WriteLine($"inputId={created.Input.ExternalInputId}  streamKey={created.StreamKey}");

var input  = await s.LiveInputs.GetAsync(created.Input.ExternalInputId);
var signed = await input.SignedPlaybackUrlAsync(3600, null);
Console.WriteLine($"playback URL: {signed.Url}");
```

## 3. Push a broadcast

```csharp
await using var pub = await Streams.BroadcastPublisher.OpenAsync(
    new Streams.PublisherArgs {
        InputId   = created.Input.ExternalInputId,
        StreamKey = created.StreamKey,
        Codecs    = new Streams.Codecs { Video = "avc1.42E01F", Audio = "opus" },
    });

pub.Write(fmp4Init);
pub.Write(fmp4Segment);
await pub.CloseAsync(Streams.CloseReason.Complete);
```

## 4. Subscribe

```csharp
await using var viewer = await Streams.BroadcastViewer.OpenAsync(
    signed.Url,
    new Streams.ViewerOpts {
        OnChunk = (init, chunk) => file.Write(chunk),
        OnClose = (reason)      => Console.WriteLine($"closed: {reason}"),
    });
```

## Other modalities

  - **[Voice](/modalities/voice/details)** — `new Voice(...)` + `Calls.OriginateAsync` + `AudioBridge.AttachAsync`
  - **[Robotics](/modalities/robotics/details)** — `new Robotics(...)` + `PublishTelemetryAsync` / `SubscribeCommandAsync`
  - **[Games](/modalities/games/details)** — `new Games(...)` + `PublishStateAsync` / `SubscribeInputs`
  - **[Data](/modalities/data/details)** — `new Data(...)` + `PublishAsync` / `SubscribeAsync`
