Hello, dial

package main

import (
    "log"
    "time"

    telequick "github.com/telequick/telequick-sdk/go/pkg"
)

func main() {{
    client, err := telequick.NewClient(
        "quic://engine.telequick.dev:9090",
        "/etc/telequick/service-account.json",
    )
    if err != nil {{ log.Fatal(err) }}

    if err := client.Dial(
        "sip:+15551234567@example.sip.livekit.cloud",  // to
        "default",                                      // trunkId
        "+18005550100",                                 // callFrom
        60_000,                                         // maxDurationMs
        1,                                              // defaultApp = PARK
        "",                                             // defaultAppArgs
        "",                                             // aiWs
        "",                                             // aiQuic
        false,                                          // autoBargeIn
        250,                                            // bargeInPatienceMs
        "",                                             // clientId override
    ); err != nil {{
        log.Fatal(err)
    }}

    time.Sleep(30 * time.Second)
}}
NewClient does not connect immediately. The first RPC method (here, Dial) opens the QUIC session, signs the JWT, and subscribes to StreamEvents — all transparent to you.

Receiving audio and events

client.OnAudioFrame = func(payload []byte) {{
    sid, pcm := client.DeserializeAudioFrame(payload)
    log.Printf("audio for %s: %d bytes", sid, len(pcm))
}}

client.OnCallEvent = func(payload []byte) {{
    sid, status := client.DeserializeCallEvent(payload)
    log.Printf("event %s -> %s", sid, status)
}}
Set callbacks before calling Dial (or any RPC), since the gateway can push events from the moment of connection.

Pushing audio out

import "os"

pcm, _ := os.ReadFile("./prompt.alaw")
const frame = 160                         // 20 ms @ 8 kHz
for i := 0; i < len(pcm); i += frame {{
    end := i + frame
    if end > len(pcm) {{ end = len(pcm) }}
    if err := client.PushAudio(
        callSid,
        pcm[i:end],
        "PCMU",
        uint64(i / frame),  // sequence_number
        false,
    ); err != nil {{ break }}
    time.Sleep(20 * time.Millisecond)
}}

Hanging up

if err := client.Terminate(callSid); err != nil {{
    log.Println("terminate:", err)
}}

Graceful shutdown

The Go SDK doesn’t expose an explicit Close() — closing the underlying QUIC connection is enough. Track in-flight call_sids in your event callback and Terminate them on shutdown:
active := map[string]struct{{}}{{}}
var mu sync.Mutex

client.OnCallEvent = func(payload []byte) {{
    sid, status := client.DeserializeCallEvent(payload)
    mu.Lock(); defer mu.Unlock()
    switch status {{
    case "COMPLETED", "FAILED", "BUSY", "NO_ANSWER":
        delete(active, sid)
    default:
        active[sid] = struct{{}}{{}}
    }}
}}

// On shutdown:
mu.Lock()
for sid := range active {{
    _ = client.Terminate(sid)
}}
mu.Unlock()