1. Install

dotnet add package ClutchCall.SDK

2. Create a live input + mint a playback URL

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

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

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

new Voice(...) + Calls.OriginateAsync + AudioBridge.AttachAsync

Robotics

new Robotics(...) + PublishTelemetryAsync / SubscribeCommandAsync

Games

new Games(...) + PublishStateAsync / SubscribeInputs

Data

new Data(...) + PublishAsync / SubscribeAsync