Skip to main content
The Burki Go SDK provides an idiomatic Go interface to the Burki Voice AI API with channel-based streaming for real-time events.

Installation

go get github.com/burki-ai/burki-go
Requirements: Go 1.18+

Quick Start

package main

import (
    "fmt"
    "log"

    burki "github.com/burki-ai/burki-go/burki"
)

func main() {
    // Initialize the client
    client := burki.NewClient("your-api-key")

    // List all assistants
    assistants, err := client.Assistants.List(nil)
    if err != nil {
        log.Fatal(err)
    }

    for _, assistant := range assistants {
        fmt.Printf("%d: %s\n", assistant.ID, assistant.Name)
    }

    // Create a new assistant
    assistant, err := client.Assistants.Create(&burki.CreateAssistantParams{
        Name:        "Support Bot",
        Description: "Customer support assistant",
        LLMSettings: &burki.LLMSettings{
            SystemPrompt: "You are a helpful customer support agent.",
            Temperature:  0.7,
        },
        TTSSettings: &burki.TTSSettings{
            Provider: "elevenlabs",
            VoiceID:  "rachel",
        },
    })
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Created assistant: %s\n", assistant.Name)
}

Configuration

Basic Configuration

client := burki.NewClient("your-api-key")

Custom Options

client := burki.NewClientWithOptions(&burki.ClientOptions{
    APIKey:  "your-api-key",
    BaseURL: "https://custom.burki.dev",
    Timeout: 60 * time.Second,
})

Using Environment Variables

import "os"

client := burki.NewClient(os.Getenv("BURKI_API_KEY"))

Resources

List Assistants

// Basic list
assistants, err := client.Assistants.List(nil)
if err != nil {
    log.Fatal(err)
}

// With pagination
assistants, err := client.Assistants.List(&burki.AssistantListParams{
    Limit: 100,
})

Get an Assistant

assistant, err := client.Assistants.Get(123)
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Name: %s\n", assistant.Name)

Create an Assistant

maxIdle := 3
assistant, err := client.Assistants.Create(&burki.CreateAssistantParams{
    Name:        "My Bot",
    Description: "A helpful customer support bot",
    LLMProvider: "openai",
    LLMSettings: &burki.LLMSettings{
        SystemPrompt: "You are helpful.",
        Temperature:  0.7,
        MaxTokens:    1000,
    },
    TTSSettings: &burki.TTSSettings{
        Provider: "elevenlabs",
        VoiceID:  "rachel",
        BackgroundSound: &burki.BackgroundSoundSettings{
            Enabled: true,
            Volume:  0.3,
        },
    },
    STTSettings: &burki.STTSettings{
        Provider: "deepgram",
        Model:    "nova-2",
        Language: "en-US",
        FluxConfig: &burki.FluxConfig{
            EotTimeoutMs: intPtr(2000),
        },
    },
    InterruptionSettings: &burki.InterruptionSettings{
        InterruptionThreshold: 3,
        MinSpeakingTime:       0.5,
    },
    ToolsSettings: &burki.ToolsSettings{
        EndCall: &burki.EndCallTool{
            Enabled:   true,
            Scenarios: []string{"user says goodbye"},
        },
        TransferCall: &burki.TransferCallTool{
            Enabled:         true,
            TransferNumbers: []string{"+14155551234"},
        },
    },
    IdleMessage:     "Are you still there?",
    MaxIdleMessages: &maxIdle,
})

Update an Assistant

name := "Updated Bot"
assistant, err := client.Assistants.Update(123, &burki.UpdateAssistantParams{
    Name: &name,
})

Delete an Assistant

err := client.Assistants.Delete(123)
if err != nil {
    log.Fatal(err)
}

Real-time Streaming

The Go SDK uses channels for real-time WebSocket streaming, providing an idiomatic Go experience.

Live Transcript Streaming

// Create the stream
stream := client.Realtime.LiveTranscript("CA123...")

// Connect to WebSocket
if err := stream.Connect(); err != nil {
    log.Fatal(err)
}
defer stream.Close()

// Optionally send ping to keep connection alive
go func() {
    for {
        time.Sleep(30 * time.Second)
        stream.SendPing()
    }
}()

// Listen for events using select
for {
    select {
    case event := <-stream.Events:
        switch e := event.(type) {
        case *burki.TranscriptEvent:
            fmt.Printf("[%s]: %s\n", e.Speaker, e.Content)
        case *burki.CallStatusEvent:
            fmt.Printf("Call status: %s\n", e.Status)
            if e.Status == "completed" {
                return
            }
        }
    case err := <-stream.Errors:
        log.Printf("Error: %v\n", err)
    case <-stream.Done:
        fmt.Println("Stream closed")
        return
    }
}

Campaign Progress Streaming

// Create the stream
stream := client.Realtime.CampaignProgress(123)

// Connect to WebSocket
if err := stream.Connect(); err != nil {
    log.Fatal(err)
}
defer stream.Close()

// Listen for events
for {
    select {
    case event := <-stream.Events:
        switch e := event.(type) {
        case *burki.CampaignProgressEvent:
            fmt.Printf("Progress: %d/%d\n", e.CompletedContacts, e.TotalContacts)
        case *burki.ContactCompletedEvent:
            fmt.Printf("Completed: %s - %s\n", e.PhoneNumber, e.Outcome)
        case *burki.CampaignCompletedEvent:
            fmt.Printf("Campaign finished! Success rate: %.2f%%\n", e.SuccessRate)
            return
        }
    case err := <-stream.Errors:
        log.Printf("Error: %v\n", err)
    case <-stream.Done:
        fmt.Println("Stream closed")
        return
    }
}

Stream Methods

// Connect to WebSocket
err := stream.Connect()

// Send ping for keepalive
stream.SendPing()

// Request current status
stream.RequestStatus()

// Close the connection
stream.Close()

// Channels available:
// stream.Events - receives typed events
// stream.Errors - receives errors
// stream.Done   - signals stream closure

Error Handling

The Go SDK provides typed errors that you can check using type assertions:
import burki "github.com/burki-ai/burki-go/burki"

client := burki.NewClient("your-api-key")

assistant, err := client.Assistants.Get(999)
if err != nil {
    switch e := err.(type) {
    case *burki.AuthenticationError:
        fmt.Println("Invalid API key")
    case *burki.NotFoundError:
        fmt.Println("Assistant not found")
    case *burki.ValidationError:
        fmt.Printf("Validation error: %s\n", e.Message)
        for field, msg := range e.FieldErrors {
            fmt.Printf("  %s: %s\n", field, msg)
        }
    case *burki.RateLimitError:
        fmt.Printf("Rate limited. Retry after %d seconds\n", e.RetryAfter)
    case *burki.ServerError:
        fmt.Println("Server error occurred")
    default:
        fmt.Printf("Unknown error: %v\n", err)
    }
    return
}

Error Types

Error TypeDescription
AuthenticationErrorInvalid or missing API key
NotFoundErrorResource not found (404)
ValidationErrorInvalid request parameters (400)
RateLimitErrorToo many requests (429)
ServerErrorInternal server error (5xx)

Complete Example

Here’s a complete example demonstrating the SDK’s capabilities:
package main

import (
    "fmt"
    "log"
    "os"
    "time"

    burki "github.com/burki-ai/burki-go/burki"
)

func main() {
    // Initialize client
    client := burki.NewClient(os.Getenv("BURKI_API_KEY"))

    // 1. Create an assistant
    assistant, err := client.Assistants.Create(&burki.CreateAssistantParams{
        Name:        "Sales Assistant",
        Description: "Outbound sales assistant",
        LLMSettings: &burki.LLMSettings{
            SystemPrompt: `You are a friendly sales representative.
                Your goal is to schedule product demos.`,
            Temperature: 0.8,
        },
        TTSSettings: &burki.TTSSettings{
            Provider: "elevenlabs",
            VoiceID:  "adam",
        },
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Created assistant: %s (ID: %d)\n", assistant.Name, assistant.ID)

    // 2. Search and purchase a phone number
    numbers, err := client.PhoneNumbers.Search(&burki.PhoneNumberSearchParams{
        Country:  "US",
        AreaCode: "415",
    })
    if err != nil {
        log.Fatal(err)
    }

    if len(numbers) > 0 {
        purchased, err := client.PhoneNumbers.Purchase(&burki.PhoneNumberPurchaseParams{
            PhoneNumber: numbers[0].PhoneNumber,
            Provider:    "twilio",
        })
        if err != nil {
            log.Fatal(err)
        }

        _, err = client.PhoneNumbers.Assign(purchased.ID, &burki.PhoneNumberAssignParams{
            AssistantID: assistant.ID,
        })
        if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("Assigned %s to assistant\n", purchased.PhoneNumber)
    }

    // 3. Upload knowledge document
    doc, err := client.Documents.UploadFromURL(assistant.ID, &burki.DocumentUploadFromURLParams{
        URL:         "https://example.com/product-guide.pdf",
        AutoProcess: true,
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Uploaded document: %s\n", doc.Filename)

    // 4. Create and start a campaign
    campaign, err := client.Campaigns.Create(&burki.CreateCampaignParams{
        Name:        "Q1 Outreach",
        AssistantID: assistant.ID,
        Contacts: []burki.CampaignContact{
            {PhoneNumber: "+14155551234", Name: "John Smith"},
            {PhoneNumber: "+14155555678", Name: "Jane Doe"},
        },
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("Created campaign: %s\n", campaign.Name)

    _, err = client.Campaigns.Start(campaign.ID)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Campaign started!")

    // 5. Monitor campaign progress
    stream := client.Realtime.CampaignProgress(campaign.ID)
    if err := stream.Connect(); err != nil {
        log.Fatal(err)
    }
    defer stream.Close()

    // Keepalive goroutine
    go func() {
        ticker := time.NewTicker(30 * time.Second)
        defer ticker.Stop()
        for range ticker.C {
            stream.SendPing()
        }
    }()

    // Listen for events
    for {
        select {
        case event := <-stream.Events:
            switch e := event.(type) {
            case *burki.CampaignProgressEvent:
                fmt.Printf("Progress: %d/%d\n", e.CompletedContacts, e.TotalContacts)
            case *burki.ContactCompletedEvent:
                fmt.Printf("Completed: %s - %s\n", e.PhoneNumber, e.Outcome)
            case *burki.CampaignCompletedEvent:
                fmt.Printf("\nCampaign finished!\n")
                fmt.Printf("Success rate: %.2f%%\n", e.SuccessRate)
                fmt.Printf("Total calls: %d\n", e.TotalContacts)
                return
            }
        case err := <-stream.Errors:
            log.Printf("Error: %v\n", err)
        case <-stream.Done:
            fmt.Println("Stream closed")
            return
        }
    }
}

// Helper function for pointer values
func intPtr(i int) *int {
    return &i
}

Next Steps

Python SDK

Check out the Python SDK with async support

JavaScript SDK

TypeScript-first SDK with full types

Real-time Streaming

Deep dive into WebSocket streaming

API Reference

Complete REST API documentation